From bf7b61bf7e22fc0c1c0bf69255f44d0139c86937 Mon Sep 17 00:00:00 2001
From: boli <boli@localhost>
Date: Thu, 24 Aug 2006 15:50:33 +0000
Subject: [PATCH] Add a configuration option to limit the number of entries that will be checked for matches during a search operation. A value of -1 or 0 will remove the limit, like the behavior of DS 5 and 6. Changed the "unlimited" values of size and time limits to be consistent with the lookthrough limit (-1 or 0). 

---
 opends/resource/schema/02-config.ldif                                |   10 +
 opends/src/server/org/opends/server/core/DirectoryServer.java        |   37 +++++
 opends/src/server/org/opends/server/api/ClientConnection.java        |   38 +++++
 opends/src/server/org/opends/server/backends/jeb/EntryContainer.java |   27 +++
 opends/src/server/org/opends/server/messages/ConfigMessages.java     |   39 +++++
 opends/src/server/org/opends/server/messages/JebMessages.java        |   13 +
 opends/src/server/org/opends/server/core/BindOperation.java          |   94 +++++++++++++
 opends/src/server/org/opends/server/core/SearchOperation.java        |    4 
 opends/resource/config/config.ldif                                   |    2 
 opends/src/server/org/opends/server/config/ConfigConstants.java      |   24 +++
 opends/src/server/org/opends/server/core/CoreConfigManager.java      |   85 +++++++++++
 opends/src/server/org/opends/server/messages/CoreMessages.java       |   27 +++
 12 files changed, 388 insertions(+), 12 deletions(-)

diff --git a/opends/resource/config/config.ldif b/opends/resource/config/config.ldif
index 189c089..3d505af 100644
--- a/opends/resource/config/config.ldif
+++ b/opends/resource/config/config.ldif
@@ -39,6 +39,7 @@
 ds-cfg-proxied-authorization-identity-mapper-dn: cn=Exact Match,cn=Identity Mappers,cn=config
 ds-cfg-size-limit: 1000
 ds-cfg-time-limit: 60 seconds
+ds-cfg-lookthrough-limit: 5000
 ds-cfg-writability-mode: enabled
 ds-cfg-bind-with-dn-requires-password: true
 ds-cfg-default-password-policy: cn=Default Password Policy,cn=Password Policies,cn=config
@@ -1003,6 +1004,7 @@
 ds-cfg-alternate-bind-dn: cn=Directory Manager
 ds-rlim-size-limit: 0
 ds-rlim-time-limit: 0
+ds-rlim-lookthrough-limit: 0
 
 dn: cn=Root DSE,cn=config
 objectClass: top
diff --git a/opends/resource/schema/02-config.ldif b/opends/resource/schema/02-config.ldif
index 4f426af..87f607e 100644
--- a/opends/resource/schema/02-config.ldif
+++ b/opends/resource/schema/02-config.ldif
@@ -974,6 +974,13 @@
   Name 'ds-cfg-database-cleaner-num-threads'
   SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE
   X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.285
+  NAME 'ds-cfg-lookthrough-limit'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE
+  X-ORIGIN 'OpenDS Directory Server' )
+attributeTypes: ( 1.3.6.1.4.1.26027.1.1.286 NAME 'ds-rlim-lookthrough-limit'
+  SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE USAGE directoryOperation
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.1
   NAME 'ds-cfg-access-control-handler' SUP top STRUCTURAL
   MUST ( cn $ ds-cfg-acl-handler-class $ ds-cfg-acl-handler-enabled )
@@ -1151,7 +1158,8 @@
   ds-cfg-single-structural-objectclass-behavior $
   ds-cfg-notify-abandoned-operations $ ds-cfg-size-limit $ ds-cfg-time-limit $
   ds-cfg-proxied-authorization-identity-mapper-dn $ ds-cfg-writability-mode $
-  ds-cfg-bind-with-dn-requires-password ) X-ORIGIN 'OpenDS Directory Server' )
+  ds-cfg-bind-with-dn-requires-password $ ds-cfg-lookthrough-limit )
+  X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.41 NAME 'ds-cfg-root-dn' SUP top
   AUXILIARY MAY ds-cfg-alternate-bind-dn X-ORIGIN 'OpenDS Directory Server' )
 objectClasses: ( 1.3.6.1.4.1.26027.1.2.42 NAME 'ds-cfg-root-dse'
diff --git a/opends/src/server/org/opends/server/api/ClientConnection.java b/opends/src/server/org/opends/server/api/ClientConnection.java
index 9f775b3..a200851 100644
--- a/opends/src/server/org/opends/server/api/ClientConnection.java
+++ b/opends/src/server/org/opends/server/api/ClientConnection.java
@@ -80,6 +80,9 @@
   // The time limit for use with this client connection.
   private int timeLimit;
 
+  // The lookthrough limit for use with this client connection.
+  private int lookthroughLimit;
+
   // The opaque information used for storing intermediate state
   // information needed across multi-stage SASL binds.
   private Object saslAuthState;
@@ -103,6 +106,7 @@
     persistentSearches = new CopyOnWriteArrayList<PersistentSearch>();
     sizeLimit          = DirectoryServer.getSizeLimit();
     timeLimit          = DirectoryServer.getTimeLimit();
+    lookthroughLimit   = DirectoryServer.getLookthroughLimit();
   }
 
 
@@ -776,6 +780,40 @@
 
 
   /**
+   * Retrieves the default maximum number of entries that should
+   * checked for matches during a search.
+   *
+   * @return  The default maximum number of entries that should
+   *          checked for matches during a search.
+   */
+  public final int getLookthroughLimit()
+  {
+    assert debugEnter(CLASS_NAME, "getLookthroughLimit");
+
+    return lookthroughLimit;
+  }
+
+
+
+  /**
+   * Specifies the default maximum number of entries that should
+   * be checked for matches during a search.
+   *
+   * @param  lookthroughLimit  The default maximum number of
+   *                           entries that should be check for
+   *                           matches during a search.
+   */
+  public final void setLookthroughLimit(int lookthroughLimit)
+  {
+    assert debugEnter(CLASS_NAME, "setLookthroughLimit",
+      String.valueOf(lookthroughLimit));
+
+    this.lookthroughLimit = lookthroughLimit;
+  }
+
+
+
+  /**
    * Retrieves the time limit that will be enforced for searches
    * performed using this client connection.
    *
diff --git a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
index 30914af..6563d81 100644
--- a/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
+++ b/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -838,6 +838,10 @@
     DatabaseEntry key = new DatabaseEntry(begin);
     List<Lock> lockList = new ArrayList<Lock>(1);
 
+    int lookthroughCount = 0;
+    int lookthroughLimit =
+        searchOperation.getClientConnection().getLookthroughLimit();
+
     try
     {
       Cursor cursor = dn2id.openCursor(null, null);
@@ -851,6 +855,15 @@
         // Step forward until we pass the ending value.
         while (status == OperationStatus.SUCCESS)
         {
+          if(lookthroughLimit > 0 && lookthroughCount > lookthroughLimit)
+          {
+            //Lookthrough limit exceeded
+            searchOperation.setResultCode(ResultCode.ADMIN_LIMIT_EXCEEDED);
+            searchOperation.appendErrorMessage(
+              getMessage(MSGID_JEB_LOOKTHROUGH_LIMIT_EXCEEDED,
+              lookthroughLimit));
+            return;
+          }
           int cmp = dn2idComparator.compare(key.getData(), end);
           if (cmp >= 0)
           {
@@ -901,6 +914,8 @@
             // Process the candidate entry.
             if (entry != null)
             {
+              lookthroughCount++;
+
               if (manageDsaIT || entry.getReferralURLs() == null)
               {
                 // Filter the entry.
@@ -1023,6 +1038,18 @@
       }
     }
 
+    // Make sure the candidate list is smaller than the lookthrough limit
+    int lookthroughLimit =
+        searchOperation.getClientConnection().getLookthroughLimit();
+    if(lookthroughLimit > 0 && entryIDList.size() > lookthroughLimit)
+    {
+      //Lookthrough limit exceeded
+      searchOperation.setResultCode(ResultCode.ADMIN_LIMIT_EXCEEDED);
+      searchOperation.appendErrorMessage(
+          getMessage(MSGID_JEB_LOOKTHROUGH_LIMIT_EXCEEDED, lookthroughLimit));
+      continueSearch = false;
+    }
+
     // Iterate through the index candidates.
     if (continueSearch)
     {
diff --git a/opends/src/server/org/opends/server/config/ConfigConstants.java b/opends/src/server/org/opends/server/config/ConfigConstants.java
index 4da841b..dc08a82 100644
--- a/opends/src/server/org/opends/server/config/ConfigConstants.java
+++ b/opends/src/server/org/opends/server/config/ConfigConstants.java
@@ -1992,6 +1992,21 @@
    */
   public static final int DEFAULT_SIZE_LIMIT = 1000;
 
+    /**
+   * The name of the configuration attribute that holds the server lookthrough
+   * limit.
+   */
+  public static final String ATTR_LOOKTHROUGH_LIMIT =
+        NAME_PREFIX_CFG + "lookthrough-limit";
+
+
+
+  /**
+   * The default value that will be used for the server lookthrough limit if
+   * no other value is given.
+   */
+  public static final int DEFAULT_LOOKTHROUGH_LIMIT = 5000;
+
 
 
   /**
@@ -3194,6 +3209,15 @@
 
 
   /**
+   * The name of the operational attribute that may be included in user
+   * entries to specify a lookthrough limit for that user.
+   */
+  public static final String OP_ATTR_USER_LOOKTHROUGH_LIMIT =
+      NAME_PREFIX_RLIM + "lookthrough-limit";
+
+
+
+  /**
    * The name of the attribute option used to indicate that a configuration
    * attribute has one or more pending values.
    */
diff --git a/opends/src/server/org/opends/server/core/BindOperation.java b/opends/src/server/org/opends/server/core/BindOperation.java
index 1769d59..8ce547c 100644
--- a/opends/src/server/org/opends/server/core/BindOperation.java
+++ b/opends/src/server/org/opends/server/core/BindOperation.java
@@ -928,9 +928,10 @@
     // the result is unknown.
     processingStartTime = System.currentTimeMillis();
     setResultCode(ResultCode.UNDEFINED);
-    boolean returnAuthzID = false;
-    int     sizeLimit     = DirectoryServer.getSizeLimit();
-    int     timeLimit     = DirectoryServer.getTimeLimit();
+    boolean returnAuthzID    = false;
+    int     sizeLimit        = DirectoryServer.getSizeLimit();
+    int     timeLimit        = DirectoryServer.getTimeLimit();
+    int     lookthroughLimit = DirectoryServer.getLookthroughLimit();
 
 
     // Set a flag to indicate that a bind operation is in progress.  This should
@@ -1473,6 +1474,50 @@
               }
 
 
+              // See if the user's entry contains a custom lookthrough limit.
+              attrType =
+                   DirectoryServer.getAttributeType(
+                       OP_ATTR_USER_LOOKTHROUGH_LIMIT, true);
+              attrList = userEntry.getAttribute(attrType);
+              if ((attrList != null) && (attrList.size() == 1))
+              {
+                Attribute a = attrList.get(0);
+                LinkedHashSet<AttributeValue>  values = a.getValues();
+                Iterator<AttributeValue> iterator = values.iterator();
+                if (iterator.hasNext())
+                {
+                  AttributeValue v = iterator.next();
+                  if (iterator.hasNext())
+                  {
+                    int msgID = MSGID_BIND_MULTIPLE_USER_LOOKTHROUGH_LIMITS;
+                    String message =
+                         getMessage(msgID, String.valueOf(userEntry.getDN()));
+                    logError(ErrorLogCategory.CORE_SERVER,
+                             ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+                  }
+                  else
+                  {
+                    try
+                    {
+                      lookthroughLimit = Integer.parseInt(v.getStringValue());
+                    }
+                    catch (Exception e)
+                    {
+                      assert debugException(CLASS_NAME, "run", e);
+
+                      int msgID =
+                          MSGID_BIND_CANNOT_PROCESS_USER_LOOKTHROUGH_LIMIT;
+                      String message =
+                           getMessage(msgID, v.getStringValue(),
+                                      String.valueOf(userEntry.getDN()));
+                      logError(ErrorLogCategory.CORE_SERVER,
+                               ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+                    }
+                  }
+                }
+              }
+
+
               pwPolicyState.handleDeprecatedStorageSchemes(simplePassword);
               pwPolicyState.clearAuthFailureTimes();
 
@@ -1930,6 +1975,48 @@
                   }
                 }
               }
+
+
+              // See if the user's entry contains a custom lookthrough limit.
+              attrType =
+                   DirectoryServer.getAttributeType(
+                       OP_ATTR_USER_LOOKTHROUGH_LIMIT, true);
+              attrList = saslAuthUserEntry.getAttribute(attrType);
+              if ((attrList != null) && (attrList.size() == 1))
+              {
+                Attribute a = attrList.get(0);
+                LinkedHashSet<AttributeValue>  values = a.getValues();
+                Iterator<AttributeValue> iterator = values.iterator();
+                if (iterator.hasNext())
+                {
+                  AttributeValue v = iterator.next();
+                  if (iterator.hasNext())
+                  {
+                    int msgID = MSGID_BIND_MULTIPLE_USER_LOOKTHROUGH_LIMITS;
+                    String message = getMessage(msgID, userDNString);
+                    logError(ErrorLogCategory.CORE_SERVER,
+                             ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+                  }
+                  else
+                  {
+                    try
+                    {
+                      lookthroughLimit = Integer.parseInt(v.getStringValue());
+                    }
+                    catch (Exception e)
+                    {
+                      assert debugException(CLASS_NAME, "run", e);
+
+                      int msgID =
+                          MSGID_BIND_CANNOT_PROCESS_USER_LOOKTHROUGH_LIMIT;
+                      String message =
+                           getMessage(msgID, v.getStringValue(), userDNString);
+                      logError(ErrorLogCategory.CORE_SERVER,
+                               ErrorLogSeverity.SEVERE_WARNING, message, msgID);
+                    }
+                  }
+                }
+              }
             }
           }
           else if (resultCode == ResultCode.SASL_BIND_IN_PROGRESS)
@@ -2037,6 +2124,7 @@
       clientConnection.setAuthenticationInfo(authInfo);
       clientConnection.setSizeLimit(sizeLimit);
       clientConnection.setTimeLimit(timeLimit);
+      clientConnection.setLookthroughLimit(lookthroughLimit);
       clientConnection.setMustChangePassword(mustChangePassword);
 
       if (returnAuthzID)
diff --git a/opends/src/server/org/opends/server/core/CoreConfigManager.java b/opends/src/server/org/opends/server/core/CoreConfigManager.java
index 45c5f55..a19ffef 100644
--- a/opends/src/server/org/opends/server/core/CoreConfigManager.java
+++ b/opends/src/server/org/opends/server/core/CoreConfigManager.java
@@ -532,8 +532,8 @@
     // Determine the default server size limit.
     msgID = MSGID_CONFIG_CORE_DESCRIPTION_SIZE_LIMIT;
     IntegerConfigAttribute sizeLimitStub =
-         new IntegerConfigAttribute(ATTR_SIZE_LIMIT, getMessage(msgID), true,
-                                    false, false, true, 0, true,
+         new IntegerConfigAttribute(ATTR_SIZE_LIMIT, getMessage(msgID), false,
+                                    false, false, true, -1, true,
                                     Integer.MAX_VALUE);
     try
     {
@@ -567,7 +567,7 @@
     msgID = MSGID_CONFIG_CORE_DESCRIPTION_TIME_LIMIT;
     IntegerWithUnitConfigAttribute timeLimitStub =
          new IntegerWithUnitConfigAttribute(ATTR_TIME_LIMIT, getMessage(msgID),
-                                            false, timeUnits, true, 0, true,
+                                            false, timeUnits, true, -1, true,
                                             Integer.MAX_VALUE);
     try
     {
@@ -598,6 +598,41 @@
     }
 
 
+    // Determine the default server lookthrough limit.
+    msgID = MSGID_CONFIG_CORE_DESCRIPTION_LOOKTHROUGH_LIMIT;
+    IntegerConfigAttribute lookthroughLimitStub =
+         new IntegerConfigAttribute(ATTR_LOOKTHROUGH_LIMIT, getMessage(msgID),
+                                    false, false, false, true, -1, true,
+                                    Integer.MAX_VALUE);
+    try
+    {
+      IntegerConfigAttribute lookthroughLimitAttr =
+           (IntegerConfigAttribute)
+           configRoot.getConfigAttribute(lookthroughLimitStub);
+      if (lookthroughLimitAttr == null)
+      {
+        DirectoryServer.setLookthroughLimit(DEFAULT_LOOKTHROUGH_LIMIT);
+      }
+      else
+      {
+        DirectoryServer.setLookthroughLimit(
+            lookthroughLimitAttr.activeIntValue());
+      }
+    }
+    catch (Exception e)
+    {
+      // An error occurred, but this should not be considered fatal.  Log an
+      // error message and use the default.
+      assert debugException(CLASS_NAME, "initializeCoreConfig", e);
+
+      logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
+               MSGID_CONFIG_CORE_INVALID_LOOKTHROUGH_LIMIT, configRoot.getDN(),
+               String.valueOf(e));
+
+      DirectoryServer.setLookthroughLimit(DEFAULT_LOOKTHROUGH_LIMIT);
+    }
+
+
     // Determine the writability mode for the Directory Server.  By default, it
     // will be writable.
     WritabilityMode writabilityMode = WritabilityMode.ENABLED;
@@ -2135,6 +2170,40 @@
     }
 
 
+    // Get the server lookthrough limit.
+    int lookthroughLimit = DEFAULT_LOOKTHROUGH_LIMIT;
+    msgID = MSGID_CONFIG_CORE_DESCRIPTION_LOOKTHROUGH_LIMIT;
+    IntegerConfigAttribute lookthroughLimitStub =
+         new IntegerConfigAttribute(ATTR_LOOKTHROUGH_LIMIT,
+             getMessage(msgID), false, false, false, true, -1, true,
+             Integer.MAX_VALUE);
+    try
+    {
+      IntegerConfigAttribute lookthroughLimitAttr =
+           (IntegerConfigAttribute)
+           configEntry.getConfigAttribute(lookthroughLimitStub);
+      if (lookthroughLimitAttr != null)
+      {
+        lookthroughLimit = lookthroughLimitAttr.pendingIntValue();
+      }
+    }
+    catch (Exception e)
+    {
+      assert debugException(CLASS_NAME, "applyNewConfiguration", e);
+
+      // An error occurred, so we will not allow this configuration change to
+      // take place.
+      if (resultCode == ResultCode.SUCCESS)
+      {
+        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
+      }
+
+      msgID = MSGID_CONFIG_CORE_INVALID_LOOKTHROUGH_LIMIT;
+      resultMessages.add(getMessage(msgID, configEntry.getDN().toString(),
+                                    String.valueOf(e)));
+    }
+
+
     // Get the server writability mode.
     HashSet<String> writabilityModes = new HashSet<String>(3);
     writabilityModes.add(WritabilityMode.ENABLED.toString());
@@ -2377,6 +2446,16 @@
       }
 
 
+      DirectoryServer.setLookthroughLimit(lookthroughLimit);
+      if (detailedResults)
+      {
+        resultMessages.add(getMessage(MSGID_CONFIG_SET_ATTRIBUTE,
+                                      ATTR_LOOKTHROUGH_LIMIT,
+                                      String.valueOf(lookthroughLimit),
+                                      configEntryDN.toString()));
+      }
+
+
       DirectoryServer.setWritabilityMode(writabilityMode);
       if (detailedResults)
       {
diff --git a/opends/src/server/org/opends/server/core/DirectoryServer.java b/opends/src/server/org/opends/server/core/DirectoryServer.java
index 4d73645..8af3d3e 100644
--- a/opends/src/server/org/opends/server/core/DirectoryServer.java
+++ b/opends/src/server/org/opends/server/core/DirectoryServer.java
@@ -378,6 +378,10 @@
   // unless overridden on a per-user basis.
   private int timeLimit;
 
+  // The maxiumum number of candidates that should be check for matches during
+  // a search.
+  private int lookthroughLimit;
+
   // The key manager provider for the Directory Server.
   private KeyManagerProvider keyManagerProvider;
 
@@ -7133,6 +7137,39 @@
 
 
   /**
+   * Retrieves the default maximum number of entries that should checked for
+   * matches during a search.
+   *
+   * @return  The default maximum number of entries that should checked for
+   *          matches during a search.
+   */
+  public static int getLookthroughLimit()
+  {
+    assert debugEnter(CLASS_NAME, "getLookthroughLimit");
+
+    return directoryServer.lookthroughLimit;
+  }
+
+
+
+  /**
+   * Specifies the default maximum number of entries that should be checked for
+   * matches during a search.
+   *
+   * @param  lookthroughLimit  The default maximum number of entries that should
+   *                           be check for matches during a search.
+   */
+  public static void setLookthroughLimit(int lookthroughLimit)
+  {
+    assert debugEnter(CLASS_NAME, "setLookthroughLimit",
+      String.valueOf(lookthroughLimit));
+
+    directoryServer.lookthroughLimit = lookthroughLimit;
+  }
+
+
+
+  /**
    * Retrieves the default maximum length of time in seconds that should be
    * allowed when processing a search.
    *
diff --git a/opends/src/server/org/opends/server/core/SearchOperation.java b/opends/src/server/org/opends/server/core/SearchOperation.java
index ebd251e..169a901 100644
--- a/opends/src/server/org/opends/server/core/SearchOperation.java
+++ b/opends/src/server/org/opends/server/core/SearchOperation.java
@@ -797,7 +797,7 @@
 
     // See if the time limit has expired.  If so, then don't send the entry and
     // indicate that the search should end.
-    if (TimeThread.getTime() >= timeLimitExpiration)
+    if ((timeLimit > 0) && (TimeThread.getTime() >= timeLimitExpiration))
     {
       setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
       appendErrorMessage(getMessage(MSGID_SEARCH_TIME_LIMIT_EXCEEDED,
@@ -1242,7 +1242,7 @@
 
     // See if the time limit has expired.  If so, then don't send the entry and
     // indicate that the search should end.
-    if (TimeThread.getTime() >= timeLimitExpiration)
+    if ((timeLimit > 0) && (TimeThread.getTime() >= timeLimitExpiration))
     {
       setResultCode(ResultCode.TIME_LIMIT_EXCEEDED);
       appendErrorMessage(getMessage(MSGID_SEARCH_TIME_LIMIT_EXCEEDED,
diff --git a/opends/src/server/org/opends/server/messages/ConfigMessages.java b/opends/src/server/org/opends/server/messages/ConfigMessages.java
index ac35bc7..fdfb12d 100644
--- a/opends/src/server/org/opends/server/messages/ConfigMessages.java
+++ b/opends/src/server/org/opends/server/messages/ConfigMessages.java
@@ -6073,6 +6073,25 @@
        CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 560;
 
 
+  /**
+   * The message ID for the description of the server lookthrough limit
+   * configuration attribute.  This does not take any arguments.
+   */
+  public static final int MSGID_CONFIG_CORE_DESCRIPTION_LOOKTHROUGH_LIMIT =
+       CATEGORY_MASK_CONFIG | SEVERITY_MASK_INFORMATIONAL | 561;
+
+
+
+  /**
+   * The message ID for the message that will be used if an error occurs while
+   * trying to process the server lookthrough limit.  This takes two arguments,
+   * which are the DN of the configuration entry and a string representation
+   * of the exception that was caught.
+   */
+  public static final int MSGID_CONFIG_CORE_INVALID_LOOKTHROUGH_LIMIT =
+       CATEGORY_MASK_CONFIG | SEVERITY_MASK_SEVERE_ERROR | 562;
+
+
 
   /**
    * Associates a set of generic messages with the message IDs defined in this
@@ -6632,9 +6651,9 @@
     registerMessage(MSGID_CONFIG_CORE_INVALID_SIZE_LIMIT,
                     "Configuration entry %s has an invalid value for " +
                     "configuration attribute " + ATTR_SIZE_LIMIT +
-                    " (it should be the a positive integer value specifying " +
-                    "the size limit to use, or -1 to indicate that no limit " +
-                    "should be enforced):  %s.");
+                    " (It should be a positive integer value specifying " +
+                    "the size limit to use, or a value of 0 or -1 to " +
+                    "indicate that no limit should be enforced):  %s.");
     registerMessage(MSGID_CONFIG_CORE_DESCRIPTION_TIME_LIMIT,
                     "Specifies the default maximum length of time that " +
                     "should be allowed when processing a search operation.  " +
@@ -8808,6 +8827,20 @@
                     "acceptable according to its internal validation.  " +
                     "However, no specific information is available regarding " +
                     "the problem(s) with the entry.");
+    registerMessage(MSGID_CONFIG_CORE_DESCRIPTION_LOOKTHROUGH_LIMIT,
+                    "Specifies the default maximum number of candidate " +
+                    "entries checked for matches when processing a search " +
+                    "operation.  This may be overridden on a per-user basis " +
+                    "by including the " + OP_ATTR_USER_LOOKTHROUGH_LIMIT +
+                    " operational attribute in the user's entry.  Changes to " +
+                    "this configuration attribute will take effect " +
+                    "immediately.");
+    registerMessage(MSGID_CONFIG_CORE_INVALID_LOOKTHROUGH_LIMIT,
+                    "Configuration entry %s has an invalid value for " +
+                    "configuration attribute " + ATTR_LOOKTHROUGH_LIMIT +
+                    " (It should be a positive integer value specifying " +
+                    "the lookthrough limit to use, or a value of 0 or -1 to " +
+                    "indicate that no limit should be enforced):  %s.");
   }
 }
 
diff --git a/opends/src/server/org/opends/server/messages/CoreMessages.java b/opends/src/server/org/opends/server/messages/CoreMessages.java
index 521ac73..f5df4dc 100644
--- a/opends/src/server/org/opends/server/messages/CoreMessages.java
+++ b/opends/src/server/org/opends/server/messages/CoreMessages.java
@@ -5824,6 +5824,25 @@
        CATEGORY_MASK_CORE | SEVERITY_MASK_MILD_ERROR | 556;
 
 
+   /**
+   * The message ID for the message that will be used if a user entry contains
+   * multiple values for the user-specific lookthrough limit attribute.
+    * This takes a single argument, which is the DN of the user entry.
+   */
+  public static final int MSGID_BIND_MULTIPLE_USER_LOOKTHROUGH_LIMITS =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_WARNING | 557;
+
+
+  /**
+   * The message ID for the message that will be used if an error occurs while
+   * trying to parse a user-specific lookthrough value as an integer. This takes
+   * two arguments, which are the provided lookthrough limit value and the DN
+   * of the user entry.
+   */
+  public static final int MSGID_BIND_CANNOT_PROCESS_USER_LOOKTHROUGH_LIMIT =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_SEVERE_WARNING | 558;
+
+
 
   /**
    * Associates a set of generic messages with the message IDs defined
@@ -7870,6 +7889,14 @@
                     "An error occured while trying to create an instance " +
                     "of class %s to use as the Directory Server work queue:  " +
                     "%s.");
+    registerMessage(MSGID_BIND_MULTIPLE_USER_LOOKTHROUGH_LIMITS,
+                    "There are multiple user-specific lookthrough limit " +
+                    "values contained in user entry %s.  The default server " +
+                    "lookthrough limit will be used.");
+    registerMessage(MSGID_BIND_CANNOT_PROCESS_USER_LOOKTHROUGH_LIMIT,
+                    "The user-specific lookthrough limit value %s contained " +
+                    "in user entry %s could not be parsed as an integer.  " +
+                    "The default server lookthrough limit will be used.");
   }
 }
 
diff --git a/opends/src/server/org/opends/server/messages/JebMessages.java b/opends/src/server/org/opends/server/messages/JebMessages.java
index 2467bf5..802971e 100644
--- a/opends/src/server/org/opends/server/messages/JebMessages.java
+++ b/opends/src/server/org/opends/server/messages/JebMessages.java
@@ -1231,6 +1231,16 @@
 
 
 
+  /**
+   * The message ID for the string representation of the result code that will
+   * be used for operations that failed because the operation lookthrough
+   *  limit was exceeded.
+   */
+  public static final int MSGID_JEB_LOOKTHROUGH_LIMIT_EXCEEDED =
+       CATEGORY_MASK_CORE | SEVERITY_MASK_INFORMATIONAL | 127;
+
+
+
 
   /**
    * Associates a set of generic messages with the message IDs defined in this
@@ -1721,5 +1731,8 @@
                     "Entry record with ID %s is not compatible with this " +
                     "version of the backend database. " +
                     "Entry version: %x");
+    registerMessage(MSGID_JEB_LOOKTHROUGH_LIMIT_EXCEEDED,
+                    "This search operation has checked the maximum of %d " +
+                    "entries for matches.");
   }
 }

--
Gitblit v1.10.0