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