mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noël Rouvignac
12.56.2016 d3520312a9ee993c50354b7c6f6b383d3611135d
OPENDJ-2609 NoSuchElementException on ldapsearch --sortorder when using corresponding vlv index

NoSuchElementException was thrown because cursor.getKey() was called before any call to cursor.next().

VLVIndex.java:
In readRange(), intialized the cursor before passing it to readRange().

ControlsTestCase.java:
Added a test.
2 files modified
37 ■■■■ changed files
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java 17 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java 20 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/backends/pluggable/VLVIndex.java
@@ -22,7 +22,7 @@
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Portions Copyright 2011-2015 ForgeRock AS
 *      Portions Copyright 2011-2016 ForgeRock AS
 */
package org.opends.server.backends.pluggable;
@@ -49,6 +49,7 @@
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.SearchScope;
import org.forgerock.opendj.ldap.schema.MatchingRule;
import org.forgerock.util.Reject;
import org.opends.server.admin.server.ConfigurationChangeListener;
import org.opends.server.admin.std.meta.BackendVLVIndexCfgDefn.Scope;
import org.opends.server.admin.std.server.BackendVLVIndexCfg;
@@ -508,9 +509,12 @@
  {
    try (Cursor<ByteString, ByteString> cursor = txn.openCursor(getName()))
    {
      final long[] selectedIDs = readRange(cursor, getEntryCount(txn), debugBuilder);
      return newDefinedSet(selectedIDs);
      if (cursor.next())
      {
        return newDefinedSet(readRange(cursor, getEntryCount(txn), debugBuilder));
      }
    }
    return null;
  }
  private int getEntryCount(final ReadableTransaction txn)
@@ -695,23 +699,24 @@
    }
  }
  private long[] readRange(final Cursor<ByteString, ByteString> cursor, final int count,
  private long[] readRange(final Cursor<ByteString, ByteString> definedCursor, final int count,
      final StringBuilder debugBuilder)
  {
    Reject.ifFalse(definedCursor.isDefined(), "Expected a defined cursor");
    long[] selectedIDs = new long[count];
    int selectedPos = 0;
    if (count > 0)
    {
      do
      {
        final ByteString key = cursor.getKey();
        final ByteString key = definedCursor.getKey();
        if (logger.isTraceEnabled())
        {
          logSearchKeyResult(key);
        }
        selectedIDs[selectedPos++] = decodeEntryIDFromVLVKey(key);
      }
      while (selectedPos < count && cursor.next());
      while (selectedPos < count && definedCursor.next());
      if (selectedPos < count)
      {
        /*
opendj-server-legacy/src/test/java/org/opends/server/backends/pluggable/ControlsTestCase.java
@@ -21,7 +21,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2015 ForgeRock AS
 *      Copyright 2015-2016 ForgeRock AS
 */
package org.opends.server.backends.pluggable;
@@ -78,7 +78,6 @@
@SuppressWarnings("javadoc")
public class ControlsTestCase extends DirectoryServerTestCase
{
  private static final String BACKEND_BASE_DN = "dc=pluggable-vlv,dc=com";
  private static final String BACKEND_NAME = "pluggable-vlv";
  private static final String VLV_FILTER = "(objectClass=person)";
@@ -406,6 +405,23 @@
    assertThat(vlvResponse.getVLVResultCode()).isEqualTo(LDAPResultCode.OFFSET_RANGE_ERROR);
  }
  @Test
  public void serverSideSortControlShouldUseVlvIndex() throws Exception
  {
    final SearchRequest request =
        newSearchRequest(BACKEND_BASE_DN, SearchScope.WHOLE_SUBTREE, VLV_FILTER)
        .addControl(new ServerSideSortRequestControl(mangleSortOrder(SORT_ORDER_1)));
    final InternalSearchOperation internalSearch = getRootConnection().processSearch(request);
    assertThat(internalSearch.getResultCode()).isEqualTo(ResultCode.SUCCESS);
    assertThat(getDNs(internalSearch.getSearchEntries())).isEqualTo(getDNs(USERS_BY_SORT_ORDER_1));
    final List<Control> responseControls = internalSearch.getResponseControls();
    assertThat(responseControls).hasSize(1);
    final ServerSideSortResponseControl sortResponse = getServerSideSortResponseControl(responseControls);
    assertThat(sortResponse.getResultCode()).isEqualTo(LDAPResultCode.SUCCESS);
  }
  @DataProvider
  private Object[][] unindexedVlvByAssertionDataProvider()
  {