From 8513213e8f8f1cd4d87a10b3218654c6988f5188 Mon Sep 17 00:00:00 2001
From: Matthew Swift <matthew.swift@forgerock.com>
Date: Tue, 31 Mar 2015 10:00:47 +0000
Subject: [PATCH] CR-6474 OPENDJ-1711 - re-implement VLV support for pluggable backends

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/EntryContainer.java |   95 ++++++++++++++++++++++-------------------------
 1 files changed, 45 insertions(+), 50 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 2428237..8c1f0e0 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
@@ -27,12 +27,13 @@
  */
 package org.opends.server.backends.pluggable;
 
-import static org.forgerock.util.Reject.checkNotNull;
 import static org.forgerock.util.Utils.closeSilently;
 import static org.opends.messages.JebMessages.*;
 import static org.opends.server.backends.pluggable.EntryIDSet.*;
 import static org.opends.server.backends.pluggable.IndexFilter.*;
 import static org.opends.server.backends.pluggable.JebFormat.*;
+import static org.opends.server.backends.pluggable.VLVIndex.encodeTargetAssertion;
+import static org.opends.server.backends.pluggable.VLVIndex.encodeVLVKey;
 import static org.opends.server.core.DirectoryServer.*;
 import static org.opends.server.protocols.ldap.LDAPResultCode.*;
 import static org.opends.server.types.AdditionalLogItem.*;
@@ -44,7 +45,6 @@
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.TreeMap;
@@ -783,7 +783,7 @@
       storage.read(new ReadOperation<Void>()
       {
         @Override
-        public Void run(ReadableTransaction txn) throws Exception
+        public Void run(final ReadableTransaction txn) throws Exception
         {
           DN aBaseDN = searchOperation.getBaseDN();
           SearchScope searchScope = searchOperation.getScope();
@@ -870,7 +870,7 @@
             {
               try
               {
-                entryIDSet = vlvIndex.evaluate(null, searchOperation, sortRequest, vlvRequest, debugBuffer);
+                entryIDSet = vlvIndex.evaluate(txn, searchOperation, sortRequest, vlvRequest, debugBuffer);
                 if (entryIDSet != null)
                 {
                   searchOperation.addResponseControl(new ServerSideSortResponseControl(SUCCESS, null));
@@ -3208,7 +3208,7 @@
     final SearchScope scope = searchOperation.getScope();
     final SearchFilter filter = searchOperation.getFilter();
 
-    final TreeMap<SortValues, Long> sortMap = new TreeMap<SortValues, Long>();
+    final TreeMap<ByteString, EntryID> sortMap = new TreeMap<ByteString, EntryID>();
     for (EntryID id : entryIDSet)
     {
       try
@@ -3216,7 +3216,7 @@
         Entry e = getEntry(txn, id);
         if (e.matchesBaseAndScope(baseDN, scope) && filter.matchesEntry(e))
         {
-          sortMap.put(new SortValues(id, e, sortOrder), id.longValue());
+          sortMap.put(encodeVLVKey(sortOrder, e, id.longValue()), id);
         }
       }
       catch (Exception e)
@@ -3238,83 +3238,81 @@
       return sortByOffset(searchOperation, vlvRequest, sortMap);
     }
 
-    return sortByGreaterThanOrEqualAssertion(searchOperation, vlvRequest, sortMap);
+    return sortByGreaterThanOrEqualAssertion(searchOperation, vlvRequest, sortOrder, sortMap);
   }
 
-  /** FIXME: Might be moved into a util.Longs class */
-  private static final long[] toArray(Collection<? extends Number> collection)
+  private static final long[] toArray(Collection<EntryID> entryIDs)
   {
-    checkNotNull(collection, "collection must not be null");
-    final long[] array = new long[collection.size()];
+    final long[] array = new long[entryIDs.size()];
     int i = 0;
-    for (Number number : collection)
+    for (EntryID entryID : entryIDs)
     {
-      array[i++] = number.longValue();
+      array[i++] = entryID.longValue();
     }
     return array;
   }
 
   private static final EntryIDSet sortByGreaterThanOrEqualAssertion(SearchOperation searchOperation,
-      VLVRequestControl vlvRequest, final TreeMap<SortValues, Long> sortMap)
+      VLVRequestControl vlvRequest, SortOrder sortOrder, final TreeMap<ByteString, EntryID> sortMap)
+      throws DirectoryException
   {
     ByteString assertionValue = vlvRequest.getGreaterThanOrEqualAssertion();
+    ByteSequence encodedTargetAssertion =
+        encodeTargetAssertion(sortOrder, assertionValue, searchOperation, sortMap.size());
 
     boolean targetFound = false;
-    int targetOffset = 0;
-    int includedBeforeCount = 0;
+    int index = 0;
+    int targetIndex = 0;
+    int startIndex = 0;
     int includedAfterCount = 0;
-
-    LinkedList<Long> idList = new LinkedList<Long>();
-    for (Map.Entry<SortValues, Long> entry : sortMap.entrySet())
+    long[] idSet = new long[sortMap.size()];
+    for (Map.Entry<ByteString, EntryID> entry : sortMap.entrySet())
     {
-      SortValues sortValues = entry.getKey();
-      long id = entry.getValue().longValue();
+      ByteString vlvKey = entry.getKey();
+      EntryID id = entry.getValue();
+      idSet[index++] = id.longValue();
 
       if (targetFound)
       {
-        idList.add(id);
         includedAfterCount++;
-        if (includedAfterCount >= vlvRequest.getBeforeCount())
+        if (includedAfterCount >= vlvRequest.getAfterCount())
         {
           break;
         }
       }
       else
       {
-        targetFound = sortValues.compareTo(assertionValue) >= 0;
-        targetOffset++;
-
+        targetFound = vlvKey.compareTo(encodedTargetAssertion) >= 0;
         if (targetFound)
         {
-          idList.add(id);
+          startIndex = Math.max(0, targetIndex - vlvRequest.getBeforeCount());
         }
-        else if (vlvRequest.getBeforeCount() > 0)
-        {
-          idList.add(id);
-          includedBeforeCount++;
-          if (includedBeforeCount > vlvRequest.getBeforeCount())
-          {
-            idList.removeFirst();
-            includedBeforeCount--;
-          }
-        }
+        targetIndex++;
       }
     }
 
-    if (!targetFound)
+    final EntryIDSet result;
+    if (targetFound)
     {
-      // No entry was found to be greater than or equal to the sort key, so the target offset will be one greater
-      // than the content count.
-      targetOffset = sortMap.size() + 1;
+      final long[] array = new long[index - startIndex];
+      System.arraycopy(idSet, startIndex, array, 0, index);
+      result = newDefinedSet(array);
     }
-
-    searchOperation.addResponseControl(new VLVResponseControl(targetOffset, sortMap.size(), LDAPResultCode.SUCCESS));
-
-    return newDefinedSet(toArray(idList));
+    else
+    {
+      /*
+       * No entry was found to be greater than or equal to the sort key, so the target offset will
+       * be one greater than the content count.
+       */
+      targetIndex = sortMap.size() + 1;
+      result = newDefinedSet();
+    }
+    searchOperation.addResponseControl(new VLVResponseControl(targetIndex, sortMap.size(), LDAPResultCode.SUCCESS));
+    return result;
   }
 
   private static final EntryIDSet sortByOffset(SearchOperation searchOperation, VLVRequestControl vlvRequest,
-      TreeMap<SortValues, Long> sortMap) throws DirectoryException
+      TreeMap<ByteString, EntryID> sortMap) throws DirectoryException
   {
     int targetOffset = vlvRequest.getOffset();
     if (targetOffset < 0)
@@ -3354,12 +3352,10 @@
     }
 
     int count = 1 + beforeCount + afterCount;
-
     long[] sortedIDs = new long[count];
-
     int treePos = 0;
     int arrayPos = 0;
-    for (Long id : sortMap.values())
+    for (EntryID id : sortMap.values())
     {
       if (treePos++ < startPos)
       {
@@ -3381,7 +3377,6 @@
     }
 
     searchOperation.addResponseControl(new VLVResponseControl(targetOffset, sortMap.size(), LDAPResultCode.SUCCESS));
-
     return newDefinedSet(sortedIDs);
   }
 

--
Gitblit v1.10.0