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

Matthew Swift
18.56.2014 ffe47ffdf1b70a54ed566cde26ad343125109500
OPENDJ-1602 (CR-5566) New pluggable storage based backend

Clean up VLV indexing:

* VLVKeyComparator is no longer needed because our storage engines won't need custom comparators. Move remaining functionality into VLVIndex
* improve encapsulation in VLVIndex
* remove duplicate code from VLVIndex.

This change is just code cleanup: the VLV indexes will not work until we have fixed up the key normalization to be compatible with memcmp().
1 files deleted
3 files modified
693 ■■■■ changed files
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SortValuesSet.java 16 ●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVIndex.java 324 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVKeyComparator.java 351 ●●●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VerifyJob.java 2 ●●● patch | view | raw | blame | history
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/SortValuesSet.java
@@ -135,7 +135,7 @@
      }
      return true;
    }
    if (vlvIndex.comparator.compare(
    if (vlvIndex.compare(
        this, entryIDs.length - 1, entryID, values) < 0)
    {
      long[] updatedEntryIDs = new long[entryIDs.length + 1];
@@ -421,7 +421,7 @@
    for(int j = entryIDs.length - 1; i <= j;)
    {
      int k = i + j >> 1;
      int l = vlvIndex.comparator.compare(this, k, entryID, values);
      int l = vlvIndex.compare(this, k, entryID, values);
      if (l < 0)
      {
        i = k + 1;
@@ -557,7 +557,7 @@
    }
    EntryID id = new EntryID(entryIDs[entryIDs.length - 1]);
    SortKey[] sortKeys = vlvIndex.sortOrder.getSortKeys();
    SortKey[] sortKeys = vlvIndex.getSortOrder().getSortKeys();
    int numValues = sortKeys.length;
    ByteString[] values = new ByteString[numValues];
    for (int i = (entryIDs.length - 1) * numValues, j = 0;
@@ -567,7 +567,7 @@
      values[j] = getValue(i);
    }
    return new SortValues(id, values, vlvIndex.sortOrder);
    return new SortValues(id, values, vlvIndex.getSortOrder());
  }
  /**
@@ -586,7 +586,7 @@
    }
    EntryID id = new EntryID(entryIDs[index]);
    SortKey[] sortKeys = vlvIndex.sortOrder.getSortKeys();
    SortKey[] sortKeys = vlvIndex.getSortOrder().getSortKeys();
    int numValues = sortKeys.length;
    ByteString[] values = new ByteString[numValues];
    for (int i = index * numValues, j = 0;
@@ -596,14 +596,14 @@
      values[j] = getValue(i);
    }
    return new SortValues(id, values, vlvIndex.sortOrder);
    return new SortValues(id, values, vlvIndex.getSortOrder());
  }
  private void updateValuesBytesOffsets()
  {
    valuesBytesOffsets = new int[entryIDs.length];
    int vBytesPos = 0;
    int numAttributes = vlvIndex.sortOrder.getSortKeys().length;
    int numAttributes = vlvIndex.getSortOrder().getSortKeys().length;
    for(int pos = 0; pos < entryIDs.length; pos++)
    {
@@ -644,7 +644,7 @@
    {
      updateValuesBytesOffsets();
    }
    int numAttributes = vlvIndex.sortOrder.getSortKeys().length;
    int numAttributes = vlvIndex.getSortOrder().getSortKeys().length;
    int vIndex = index / numAttributes;
    int vOffset = index % numAttributes;
    int vBytesPos = valuesBytesOffsets[vIndex];
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVIndex.java
@@ -26,6 +26,9 @@
 */
package org.opends.server.backends.pluggable;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -89,12 +92,10 @@
{
  private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
  /** The comparator for vlvIndex keys. */
  public VLVKeyComparator comparator;
  /** The limit on the number of entry IDs that may be indexed by one key. */
  private int sortedSetCapacity = 4000;
  /** The SortOrder in use by this VLV index to sort the entries. */
  public SortOrder sortOrder;
  private SortOrder sortOrder;
  /** The cached count of entries in this index. */
  private final AtomicInteger count;
@@ -129,7 +130,7 @@
   * @throws ConfigException if a error occurs while reading the VLV index
   * configuration
   */
  public VLVIndex(BackendVLVIndexCfg config, State state, Storage env,
  VLVIndex(BackendVLVIndexCfg config, State state, Storage env,
                  EntryContainer entryContainer, ReadableStorage txn)
      throws StorageRuntimeException, ConfigException
  {
@@ -151,48 +152,7 @@
      throw new ConfigException(msg);
    }
    String[] sortAttrs = config.getSortOrder().split(" ");
    SortKey[] sortKeys = new SortKey[sortAttrs.length];
    MatchingRule[] orderingRules = new MatchingRule[sortAttrs.length];
    boolean[] ascending = new boolean[sortAttrs.length];
    for(int i = 0; i < sortAttrs.length; i++)
    {
      try
      {
        if(sortAttrs[i].startsWith("-"))
        {
          ascending[i] = false;
          sortAttrs[i] = sortAttrs[i].substring(1);
        }
        else
        {
          ascending[i] = true;
          if(sortAttrs[i].startsWith("+"))
          {
            sortAttrs[i] = sortAttrs[i].substring(1);
          }
        }
      }
      catch(Exception e)
      {
        throw new ConfigException(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
      }
      AttributeType attrType =
          DirectoryServer.getAttributeType(sortAttrs[i].toLowerCase());
      if(attrType == null)
      {
        LocalizableMessage msg =
            ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortAttrs[i], treeName);
        throw new ConfigException(msg);
      }
      sortKeys[i] = new SortKey(attrType, ascending[i]);
      orderingRules[i] = attrType.getOrderingMatchingRule();
    }
    this.sortOrder = new SortOrder(sortKeys);
    this.comparator = new VLVKeyComparator(orderingRules, ascending);
    this.sortOrder = new SortOrder(parseSortKeys(config));
    this.state = state;
    this.trusted = state.getIndexTrustState(txn, this);
    if (!trusted && entryContainer.getHighestEntryID(txn).longValue() == 0)
@@ -206,6 +166,49 @@
    this.config.addChangeListener(this);
  }
  private SortKey[] parseSortKeys(BackendVLVIndexCfg config)
      throws ConfigException
  {
    String[] sortAttrs = config.getSortOrder().split(" ");
    SortKey[] sortKeys = new SortKey[sortAttrs.length];
    for (int i = 0; i < sortAttrs.length; i++)
    {
      final boolean ascending;
      try
      {
        if (sortAttrs[i].startsWith("-"))
        {
          ascending = false;
          sortAttrs[i] = sortAttrs[i].substring(1);
        }
        else
        {
          ascending = true;
          if (sortAttrs[i].startsWith("+"))
          {
            sortAttrs[i] = sortAttrs[i].substring(1);
          }
        }
      }
      catch (Exception e)
      {
        throw new ConfigException(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(
            sortKeys[i], treeName));
      }
      AttributeType attrType = DirectoryServer.getAttributeType(sortAttrs[i]
          .toLowerCase());
      if (attrType == null)
      {
        LocalizableMessage msg = ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(
            sortAttrs[i], treeName);
        throw new ConfigException(msg);
      }
      sortKeys[i] = new SortKey(attrType, ascending);
    }
    return sortKeys;
  }
  private SearchScope valueOf(Scope cfgScope)
  {
    final Enum toFind = SearchScope.Enum.valueOf(cfgScope.name());
@@ -394,7 +397,7 @@
   * JE database.
   * @throws DirectoryException If a Directory Server error occurs.
   */
  public SortValuesSet getSortValuesSet(ReadableStorage txn, long entryID,
  private SortValuesSet getSortValuesSet(ReadableStorage txn, long entryID,
      ByteString[] values, AttributeType[] types) throws StorageRuntimeException,
      DirectoryException
  {
@@ -520,7 +523,7 @@
    while(true)
    {
      ByteString key;
      final ByteString key;
      if(av != null)
      {
        if(dv != null)
@@ -1111,16 +1114,6 @@
  }
  /**
   * Get the sorted set capacity configured for this VLV index.
   *
   * @return The sorted set capacity.
   */
  public int getSortedSetCapacity()
  {
    return sortedSetCapacity;
  }
  /**
   * Indicates if the given entry should belong in this VLV index.
   *
   * @param entry The entry to check.
@@ -1154,43 +1147,14 @@
      return false;
    }
    String[] sortAttrs = cfg.getSortOrder().split(" ");
    SortKey[] sortKeys = new SortKey[sortAttrs.length];
    MatchingRule[] orderingRules = new MatchingRule[sortAttrs.length];
    boolean[] ascending = new boolean[sortAttrs.length];
    for(int i = 0; i < sortAttrs.length; i++)
    try
    {
      try
      {
        if(sortAttrs[i].startsWith("-"))
        {
          ascending[i] = false;
          sortAttrs[i] = sortAttrs[i].substring(1);
        }
        else
        {
          ascending[i] = true;
          if(sortAttrs[i].startsWith("+"))
          {
            sortAttrs[i] = sortAttrs[i].substring(1);
          }
        }
      }
      catch(Exception e)
      {
        unacceptableReasons.add(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
        return false;
      }
      AttributeType attrType = DirectoryServer.getAttributeType(sortAttrs[i].toLowerCase());
      if(attrType == null)
      {
        LocalizableMessage msg = ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortAttrs[i], treeName);
        unacceptableReasons.add(msg);
        return false;
      }
      sortKeys[i] = new SortKey(attrType, ascending[i]);
      orderingRules[i] = attrType.getOrderingMatchingRule();
      parseSortKeys(cfg);
    }
    catch (ConfigException e)
    {
      unacceptableReasons.add(e.getMessageObject());
      return false;
    }
    return true;
@@ -1268,50 +1232,15 @@
    // Update the sort order only if changed.
    if (!config.getSortOrder().equals(cfg.getSortOrder()))
    {
      String[] sortAttrs = cfg.getSortOrder().split(" ");
      SortKey[] sortKeys = new SortKey[sortAttrs.length];
      MatchingRule[] orderingRules = new MatchingRule[sortAttrs.length];
      boolean[] ascending = new boolean[sortAttrs.length];
      for(int i = 0; i < sortAttrs.length; i++)
      try
      {
        try
        {
          if(sortAttrs[i].startsWith("-"))
          {
            ascending[i] = false;
            sortAttrs[i] = sortAttrs[i].substring(1);
          }
          else
          {
            ascending[i] = true;
            if(sortAttrs[i].startsWith("+"))
            {
              sortAttrs[i] = sortAttrs[i].substring(1);
            }
          }
        }
        catch(Exception e)
        {
          ccr.addMessage(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
          ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
        }
        AttributeType attrType =
            DirectoryServer.getAttributeType(sortAttrs[i].toLowerCase());
        if(attrType == null)
        {
          ccr.addMessage(ERR_JEB_CONFIG_VLV_INDEX_UNDEFINED_ATTR.get(sortKeys[i], treeName));
          ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
        }
        else
        {
          sortKeys[i] = new SortKey(attrType, ascending[i]);
          orderingRules[i] = attrType.getOrderingMatchingRule();
        }
        this.sortOrder = new SortOrder(parseSortKeys(cfg));
      }
      this.sortOrder = new SortOrder(sortKeys);
      this.comparator = new VLVKeyComparator(orderingRules, ascending);
      catch (ConfigException e)
      {
        ccr.addMessage(e.getMessageObject());
        ccr.setResultCode(ResultCode.INVALID_ATTRIBUTE_SYNTAX);
      }
      // We have to close the database and open it using the new comparator.
      entryContainer.exclusiveLock.lock();
@@ -1357,4 +1286,127 @@
    this.config = cfg;
  }
  /**
   * Compares the contents in the provided values set with the given values to
   * determine their relative order. A null value is always considered greater
   * then a non null value. If all attribute values are the same, the entry ID
   * will be used to determine the ordering. If the given attribute values array
   * does not contain all the values in the sort order, any missing values will
   * be considered as a unknown or wildcard value instead of a non existent
   * value. When comparing partial information, only values available in both
   * the values set and the given values will be used to determine the ordering.
   * If all available information is the same, 0 will be returned.
   *
   * @param set
   *          The sort values set to containing the values.
   * @param index
   *          The index of the values in the set.
   * @param entryID
   *          The entry ID to use in the comparison.
   * @param values
   *          The values to use in the comparison.
   * @return A negative integer if the values in the set should come before the
   *         given values in ascending order, a positive integer if the values
   *         in the set should come after the given values in ascending order,
   *         or zero if there is no difference between the values with regard to
   *         ordering.
   * @throws StorageRuntimeException
   *           If an error occurs during an operation on a JE database.
   * @throws DirectoryException
   *           If an error occurs while trying to normalize the value (e.g., if
   *           it is not acceptable for use with the associated equality
   *           matching rule).
   */
  int compare(SortValuesSet set, int index, long entryID,
      ByteSequence... values) throws StorageRuntimeException,
      DirectoryException
  {
    SortKey[] sortKeys = sortOrder.getSortKeys();
    for (int j = 0; j < sortKeys.length; j++)
    {
      MatchingRule orderingRule = sortKeys[j].getOrderingRule();
      boolean ascending = sortKeys[j].ascending();
      if (j >= values.length)
      {
        break;
      }
      ByteString b1Bytes = set.getValue((index * sortKeys.length) + j);
      ByteString b2Bytes = null;
      if (values[j] != null)
      {
        try
        {
          b2Bytes = orderingRule.normalizeAttributeValue(values[j]);
        }
        catch (DecodeException e)
        {
          throw new DirectoryException(ResultCode.INVALID_ATTRIBUTE_SYNTAX,
              e.getMessageObject(), e);
        }
      }
      // A null value will always come after a non-null value.
      if (b1Bytes == null)
      {
        if (b2Bytes == null)
        {
          continue;
        }
        else
        {
          return 1;
        }
      }
      else if (b2Bytes == null)
      {
        return -1;
      }
      final Comparator<ByteSequence> comp = orderingRule.comparator();
      final int result = ascending ? comp.compare(b1Bytes, b2Bytes) : comp
          .compare(b2Bytes, b1Bytes);
      if (result != 0)
      {
        return result;
      }
    }
    if (entryID != -1)
    {
      // If we've gotten here, then we can't tell a difference between the sets
      // of values, so sort based on entry ID.
      return compare(set.getEntryIDs()[index], entryID);
    }
    // If we've gotten here, then we can't tell the difference between the sets
    // of available values and the entry ID is not available. Just return 0.
    return 0;
  }
  private int compare(long l1, long l2)
  {
    final long difference = l1 - l2;
    if (difference < 0)
    {
      return -1;
    }
    else if (difference > 0)
    {
      return 1;
    }
    else
    {
      return 0;
    }
  }
  SortOrder getSortOrder()
  {
    return sortOrder;
  }
}
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VLVKeyComparator.java
File was deleted
opendj3-server-dev/src/server/org/opends/server/backends/pluggable/VerifyJob.java
@@ -965,7 +965,7 @@
              continue;
            }
            SortValues entryValues = new SortValues(id, entry, vlvIndex.sortOrder);
            SortValues entryValues = new SortValues(id, entry, vlvIndex.getSortOrder());
            if(entryValues.compareTo(values) != 0)
            {
              errorCount++;