From 6b2e40457bfb2437f932e78ac04ee4d08878c1b6 Mon Sep 17 00:00:00 2001
From: Yannick Lecaillez <yannick.lecaillez@forgerock.com>
Date: Tue, 19 May 2015 09:40:14 +0000
Subject: [PATCH] OPENDJ-1973: Unindexed searches should limit dn2id cursoring based on hard-coded limit and user's look through limit.

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java |   47 ++++++++++++++++++++++++++++++-----------------
 1 files changed, 30 insertions(+), 17 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
index 5ca5b2b..b725930 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java
@@ -865,7 +865,11 @@
 
             if (!isBelowFilterThreshold(entryIDSet))
             {
-              final EntryIDSet scopeSet = getIDSetFromScope(txn, aBaseDN, searchScope);
+              final int lookThroughLimit = searchOperation.getClientConnection().getLookthroughLimit();
+              final int idSetLimit =
+                  lookThroughLimit == 0 ? SCOPE_IDSET_LIMIT : Math.min(SCOPE_IDSET_LIMIT, lookThroughLimit);
+
+              final EntryIDSet scopeSet = getIDSetFromScope(txn, aBaseDN, searchScope, idSetLimit);
               entryIDSet.retainAll(scopeSet);
               if (debugBuffer != null)
               {
@@ -969,8 +973,8 @@
           return null;
         }
 
-        private EntryIDSet getIDSetFromScope(final ReadableTransaction txn, DN aBaseDN, SearchScope searchScope)
-            throws DirectoryException
+        private EntryIDSet getIDSetFromScope(final ReadableTransaction txn, DN aBaseDN, SearchScope searchScope,
+            int idSetLimit) throws DirectoryException
         {
           final EntryIDSet scopeSet;
           try
@@ -986,14 +990,14 @@
             case SINGLE_LEVEL:
               try (final SequentialCursor<?, EntryID> scopeCursor = dn2id.openChildrenCursor(txn, aBaseDN))
               {
-                scopeSet = newIDSetFromCursor(scopeCursor, false);
+                scopeSet = newIDSetFromCursor(scopeCursor, false, idSetLimit);
               }
               break;
             case SUBORDINATES:
             case WHOLE_SUBTREE:
               try (final SequentialCursor<?, EntryID> scopeCursor = dn2id.openSubordinatesCursor(txn, aBaseDN))
               {
-                scopeSet = newIDSetFromCursor(scopeCursor, searchScope.equals(SearchScope.WHOLE_SUBTREE));
+                scopeSet = newIDSetFromCursor(scopeCursor, searchScope.equals(SearchScope.WHOLE_SUBTREE), idSetLimit);
               }
               break;
             default:
@@ -1016,23 +1020,32 @@
     }
   }
 
-  private static EntryIDSet newIDSetFromCursor(SequentialCursor<?, EntryID> cursor, boolean includeCurrent)
+  private static EntryIDSet newIDSetFromCursor(SequentialCursor<?, EntryID> cursor, boolean includeCurrent,
+      int idSetLimit)
   {
-    long ids[] = new long[SCOPE_IDSET_LIMIT];
+    long entryIDs[] = new long[idSetLimit];
     int offset = 0;
-    if (includeCurrent) {
-      ids[offset++] = cursor.getValue().longValue();
-    }
-    for(; offset < ids.length && cursor.next() ; offset++) {
-      ids[offset] = cursor.getValue().longValue();
+    if (includeCurrent)
+    {
+      entryIDs[offset++] = cursor.getValue().longValue();
     }
 
-    ids = Arrays.copyOf(ids, offset);
-    Arrays.sort(ids);
+    while(offset < idSetLimit && cursor.next())
+    {
+      entryIDs[offset++] = cursor.getValue().longValue();
+    }
 
-    return offset == SCOPE_IDSET_LIMIT
-        ? EntryIDSet.newUndefinedSet()
-        : EntryIDSet.newDefinedSet(ids);
+    if (offset == idSetLimit && cursor.next())
+    {
+      return EntryIDSet.newUndefinedSet();
+    }
+    else if (offset != idSetLimit)
+    {
+      entryIDs = Arrays.copyOf(entryIDs, offset);
+    }
+    Arrays.sort(entryIDs);
+
+    return EntryIDSet.newDefinedSet(entryIDs);
   }
 
   private <E1 extends Exception, E2 extends Exception>

--
Gitblit v1.10.0