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

ludovicp
25.40.2010 31a3bbd4e956110d2bd6107866cf774f4da340b5
Resolves an issue in Import due to entries with multiple RDNs.
This patch changes the key format used by the DN2ID database. Rebuilding the index is required.
12 files modified
923 ■■■■ changed files
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2ID.java 73 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2URI.java 60 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java 110 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ID2Entry.java 13 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/JebFormat.java 144 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VerifyJob.java 30 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java 209 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/IndexBuffer.java 168 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/tools/DBTest.java 16 ●●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/types/RDN.java 75 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestEntryContainer.java 13 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java 12 ●●●● patch | view | raw | blame | history
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2ID.java
@@ -22,14 +22,13 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends.jeb;
import com.sleepycat.je.*;
import org.opends.server.types.DN;
import org.opends.server.util.StaticUtils;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
@@ -50,7 +49,9 @@
  /**
   * The key comparator used for the DN database.
   */
  private Comparator<byte[]> dn2idComparator;
  private final Comparator<byte[]> comparator;
  private final int prefixRDNComponents;
  /**
   * Create a DN2ID instance for the DN database in a given entryContainer.
@@ -66,7 +67,8 @@
  {
    super(name, env, entryContainer);
    dn2idComparator = new EntryContainer.KeyReverseComparator();
    comparator = new AttributeIndex.KeyComparator();
    prefixRDNComponents = entryContainer.getBaseDN().getNumComponents();
    DatabaseConfig dn2idConfig = new DatabaseConfig();
    if(env.getConfig().getReadOnly())
@@ -88,22 +90,15 @@
    }
    this.dbConfig = dn2idConfig;
    this.dbConfig.setKeyPrefixing(true);
    //This line causes an unchecked cast error if the SuppressWarnings
    //annotation is removed at the beginning of this method.
    this.dbConfig.setBtreeComparator((Class<? extends Comparator<byte[]>>)
                                     dn2idComparator.getClass());
                                     comparator.getClass());
  }
  /**
   * Create a DN database key from an entry DN.
   * @param dn The entry DN.
   * @return A DatabaseEntry containing the key.
   */
  private static DatabaseEntry DNdata(DN dn)
  {
    byte[] normDN = StaticUtils.getBytes(dn.toNormalizedString());
    return new DatabaseEntry(normDN);
  }
  /**
   * Insert a new record into the DN database.
@@ -119,7 +114,8 @@
  public boolean insert(Transaction txn, DN dn, EntryID id)
       throws DatabaseException
  {
    DatabaseEntry key = DNdata(dn);
    DatabaseEntry key = new DatabaseEntry(
        JebFormat.dnToDNKey(dn, prefixRDNComponents));
    DatabaseEntry data = id.getDatabaseEntry();
    OperationStatus status;
@@ -147,7 +143,8 @@
  public boolean put(Transaction txn, DN dn, EntryID id)
       throws DatabaseException
  {
    DatabaseEntry key = DNdata(dn);
    DatabaseEntry key = new DatabaseEntry(
        JebFormat.dnToDNKey(dn, prefixRDNComponents));
    DatabaseEntry data = id.getDatabaseEntry();
    OperationStatus status;
@@ -170,16 +167,11 @@
   * @throws DatabaseException If an error occurred while attempting to write
   * the record.
   */
  public boolean putRaw(Transaction txn, DatabaseEntry key, DatabaseEntry data)
  public OperationStatus put(Transaction txn, DatabaseEntry key,
                             DatabaseEntry data)
       throws DatabaseException
  {
    OperationStatus status;
    status = put(txn, key, data);
    if (status != OperationStatus.SUCCESS)
    {
      return false;
    }
    return true;
    return super.put(txn, key, data);
  }
  /**
@@ -194,7 +186,9 @@
  public boolean remove(Transaction txn, DN dn)
       throws DatabaseException
  {
    DatabaseEntry key = DNdata(dn);
    DatabaseEntry key = new DatabaseEntry(
        JebFormat.dnToDNKey(dn, prefixRDNComponents)
    );
    OperationStatus status = delete(txn, key);
    if (status != OperationStatus.SUCCESS)
@@ -205,6 +199,16 @@
  }
  /**
   * {@inheritDoc}
   */
  @Override
  protected OperationStatus delete(Transaction txn, DatabaseEntry key)
      throws DatabaseException
  {
    return super.delete(txn, key);
  }
  /**
   * Fetch the entry ID for a given DN.
   * @param txn A JE database transaction to be used for the database read, or
   * null if none is required.
@@ -216,7 +220,9 @@
  public EntryID get(Transaction txn, DN dn, LockMode lockMode)
       throws DatabaseException
  {
    DatabaseEntry key = DNdata(dn);
    DatabaseEntry key = new DatabaseEntry(
        JebFormat.dnToDNKey(dn, prefixRDNComponents)
    );
    DatabaseEntry data = new DatabaseEntry();
    OperationStatus status;
@@ -229,12 +235,23 @@
  }
  /**
   * {@inheritDoc}
   */
  @Override
  public OperationStatus read(Transaction txn,
                              DatabaseEntry key, DatabaseEntry data,
                              LockMode lockMode)
  {
    return super.read(txn, key, data, lockMode);
  }
  /**
   * Gets the comparator for records stored in this database.
   *
   * @return The comparator for records stored in this database.
   */
  public Comparator<byte[]> getComparator()
  {
    return dn2idComparator;
    return comparator;
  }
}
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2URI.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends.jeb;
@@ -37,11 +37,7 @@
import org.opends.server.util.StaticUtils;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.*;
import static org.opends.server.util.ServerConstants.ATTR_REFERRAL_URL;
import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -65,7 +61,10 @@
  /**
   * The key comparator used for the DN database.
   */
  private Comparator<byte[]> dn2uriComparator;
  private final Comparator<byte[]> dn2uriComparator;
  private final int prefixRDNComponents;
  /**
@@ -100,7 +99,8 @@
  {
    super(name, env, entryContainer);
    dn2uriComparator = new EntryContainer.KeyReverseComparator();
    dn2uriComparator = new AttributeIndex.KeyComparator();
    prefixRDNComponents = entryContainer.getBaseDN().getNumComponents();
    DatabaseConfig dn2uriConfig = new DatabaseConfig();
    if(env.getConfig().getReadOnly())
@@ -140,10 +140,10 @@
   * @return true if the record was inserted, false if it was not.
   * @throws DatabaseException If an error occurs in the JE database.
   */
  public boolean insert(Transaction txn, DN dn, String labeledURI)
  private boolean insert(Transaction txn, DN dn, String labeledURI)
       throws DatabaseException
  {
    byte[] normDN = StaticUtils.getBytes(dn.toNormalizedString());
    byte[] normDN = JebFormat.dnToDNKey(dn, prefixRDNComponents);
    byte[] URIBytes = StaticUtils.getBytes(labeledURI);
    DatabaseEntry key = new DatabaseEntry(normDN);
    DatabaseEntry data = new DatabaseEntry(URIBytes);
@@ -173,7 +173,7 @@
  public boolean delete(Transaction txn, DN dn)
       throws DatabaseException
  {
    byte[] normDN = StaticUtils.getBytes(dn.toNormalizedString());
    byte[] normDN = JebFormat.dnToDNKey(dn, prefixRDNComponents);
    DatabaseEntry key = new DatabaseEntry(normDN);
    OperationStatus status;
@@ -199,7 +199,7 @@
       throws DatabaseException
  {
    CursorConfig cursorConfig = null;
    byte[] normDN = StaticUtils.getBytes(dn.toNormalizedString());
    byte[] normDN = JebFormat.dnToDNKey(dn, prefixRDNComponents);
    byte[] URIBytes = StaticUtils.getBytes(labeledURI);
    DatabaseEntry key = new DatabaseEntry(normDN);
    DatabaseEntry data = new DatabaseEntry(URIBytes);
@@ -552,8 +552,7 @@
             dn = entryContainer.getParentWithinBase(dn))
        {
          // Look for a record whose key matches the current DN.
          String normDN = dn.toNormalizedString();
          key.setData(StaticUtils.getBytes(normDN));
          key.setData(JebFormat.dnToDNKey(dn, prefixRDNComponents));
          OperationStatus status =
             cursor.getSearchKey(key, data, LockMode.DEFAULT);
          if (status == OperationStatus.SUCCESS)
@@ -625,9 +624,12 @@
     * find subordinates of the base entry from the top of the tree
     * downwards.
     */
    DN baseDN = searchOp.getBaseDN();
    String normBaseDN = baseDN.toNormalizedString();
    byte[] suffix = StaticUtils.getBytes("," + normBaseDN);
    byte[] baseDN = JebFormat.dnToDNKey(searchOp.getBaseDN(),
                                          prefixRDNComponents);
    byte[] suffix = Arrays.copyOf(baseDN, baseDN.length+1);
    suffix[suffix.length-1] = 0x00;
    byte[] end = suffix.clone();
    end[end.length-1] = (byte) (end[end.length-1] + 1);
    /*
     * Set the ending value to a value of equal length but slightly
@@ -635,7 +637,6 @@
     * reverse order we must set the first byte (the comma).
     * No possibility of overflow here.
     */
    byte[] end = null;
    DatabaseEntry data = new DatabaseEntry();
    DatabaseEntry key = new DatabaseEntry(suffix);
@@ -652,11 +653,6 @@
             status == OperationStatus.SUCCESS;
             status = cursor.getNextNoDup(key, data, LockMode.DEFAULT))
        {
          if (end == null)
          {
            end = suffix.clone();
            end[0] = (byte) (end[0] + 1);
          }
          int cmp = dn2uriComparator.compare(key.getData(), end);
          if (cmp >= 0)
@@ -666,13 +662,14 @@
          }
          // We have found a subordinate referral.
          DN dn = DN.decode(ByteString.wrap(key.getData()));
          DN dn = JebFormat.dnFromDNKey(key.getData(), 0, key.getSize(),
                                        entryContainer.getBaseDN());
          // Make sure the referral is within scope.
          if (searchOp.getScope() == SearchScope.SINGLE_LEVEL)
          {
            if ((dn.getNumComponents() !=
                 baseDN.getNumComponents() + 1))
            if(JebFormat.findDNKeyParent(key.getData(), 0,
                                       key.getSize()) == baseDN.length)
            {
              continue;
            }
@@ -705,6 +702,7 @@
              {
                if (ldapurl.getBaseDN().isNullDN())
                {
                  ldapurl.setBaseDN(dn);
                }
                ldapurl.getAttributes().clear();
@@ -762,14 +760,4 @@
    return true;
  }
  /**
   * Gets the comparator for records stored in this database.
   *
   * @return The comparator used for records stored in this database.
   */
  public Comparator<byte[]> getComparator()
  {
    return dn2uriComparator;
  }
}
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
@@ -1274,7 +1274,10 @@
     * "cn=joe,ou=people,dc=example,dc=com" will appear after the entry
     * "ou=people,dc=example,dc=com".
     */
    byte[] suffix = StaticUtils.getBytes("," + baseDN.toNormalizedString());
    byte[] baseDNKey = JebFormat.dnToDNKey(baseDN,
                                             this.baseDN.getNumComponents());
    byte[] suffix = Arrays.copyOf(baseDNKey, baseDNKey.length+1);
    suffix[suffix.length-1] = 0x00;
    /*
     * Set the ending value to a value of equal length but slightly
@@ -1283,7 +1286,7 @@
     * No possibility of overflow here.
     */
    byte[] end = suffix.clone();
    end[0] = (byte) (end[0] + 1);
    end[end.length-1] = (byte) (end[end.length-1] + 1);
    // Set the starting value.
    byte[] begin;
@@ -1352,14 +1355,13 @@
          // We have found a subordinate entry.
          EntryID entryID = new EntryID(data);
          DN dn = DN.decode(ByteString.wrap(key.getData()));
          boolean isInScope = true;
          if (searchScope == SearchScope.SINGLE_LEVEL)
          {
            // Check if this entry is an immediate child.
            if ((dn.getNumComponents() !=
              baseDN.getNumComponents() + 1))
            if(JebFormat.findDNKeyParent(key.getData(), 0,
                                       key.getSize()) == baseDNKey.length)
            {
              isInScope = false;
            }
@@ -1911,15 +1913,17 @@
       * find subordinates of the target entry from the top of the tree
       * downwards.
       */
      byte[] suffix = StaticUtils.getBytes("," +
          entryDN.toNormalizedString());
      byte[] entryDNKey = JebFormat.dnToDNKey(entryDN,
                                               this.baseDN.getNumComponents());
      byte[] suffix = Arrays.copyOf(entryDNKey, entryDNKey.length+1);
      suffix[suffix.length-1] = 0x00;
      /*
       * Set the ending value to a value of equal length but slightly
       * greater than the suffix.
       */
      byte[] end = suffix.clone();
      end[0] = (byte) (end[0] + 1);
      end[end.length-1] = (byte) (end[end.length-1] + 1);
      int subordinateEntriesDeleted = 0;
@@ -1976,7 +1980,6 @@
           * we have been deleting from the bottom of the tree upwards.
           */
          EntryID entryID = new EntryID(data);
          DN subordinateDN = DN.decode(ByteString.wrap(key.getData()));
          // Invoke any subordinate delete plugins on the entry.
          if (!deleteOperation.isSynchronizationOperation())
@@ -1993,13 +1996,14 @@
            {
              Message message =
                      ERR_JEB_DELETE_ABORTED_BY_SUBORDINATE_PLUGIN.get(
                      subordinateDN.toString());
                      JebFormat.dnFromDNKey(key.getData(), 0, 0, getBaseDN()).
                          toString());
              throw new DirectoryException(
                  DirectoryServer.getServerErrorResultCode(), message);
            }
          }
          deleteEntry(txn, indexBuffer, true, entryDN, subordinateDN, entryID);
          deleteEntry(txn, indexBuffer, true, entryDN, key, entryID);
          subordinateEntriesDeleted++;
          if(deleteOperation != null)
@@ -2081,30 +2085,38 @@
      IndexBuffer indexBuffer,
      boolean manageDsaIT,
      DN targetDN,
      DN leafDN,
      DatabaseEntry leafDNKey,
      EntryID leafID)
  throws DatabaseException, DirectoryException, JebException
  {
    if(leafID == null || leafDN == null)
    if(leafID == null || leafDNKey == null)
    {
      // Read the entry ID from dn2id.
      leafDN = targetDN;
      leafID = dn2id.get(txn, leafDN, LockMode.RMW);
      if (leafID == null)
      if(leafDNKey == null)
      {
        leafDNKey =
            new DatabaseEntry(JebFormat.dnToDNKey(
                targetDN, this.baseDN.getNumComponents()));
      }
      DatabaseEntry value = new DatabaseEntry();
      OperationStatus status;
      status = dn2id.read(txn, leafDNKey, value, LockMode.RMW);
      if (status != OperationStatus.SUCCESS)
      {
        Message message =
          ERR_JEB_DELETE_NO_SUCH_OBJECT.get(leafDN.toString());
          ERR_JEB_DELETE_NO_SUCH_OBJECT.get(leafDNKey.toString());
        DN matchedDN = getMatchedDN(baseDN);
        throw new DirectoryException(ResultCode.NO_SUCH_OBJECT,
            message, matchedDN, null);
      }
      leafID = new EntryID(value);
    }
    // Remove from dn2id.
    if (!dn2id.remove(txn, leafDN))
    if (dn2id.delete(txn, leafDNKey) != OperationStatus.SUCCESS)
    {
      // Do not expect to ever come through here.
      Message message = ERR_JEB_DELETE_NO_SUCH_OBJECT.get(leafDN.toString());
      Message message = ERR_JEB_DELETE_NO_SUCH_OBJECT.get(leafDNKey.toString());
      DN matchedDN = getMatchedDN(baseDN);
      throw new DirectoryException(ResultCode.NO_SUCH_OBJECT,
          message, matchedDN, null);
@@ -2203,7 +2215,7 @@
    EntryCache<?> entryCache = DirectoryServer.getEntryCache();
    if (entryCache != null)
    {
      entryCache.removeEntry(leafDN);
      entryCache.removeEntry(entry.getDN());
    }
  }
@@ -2563,15 +2575,17 @@
       * find subordinates of the target entry from the top of the tree
       * downwards.
       */
      byte[] suffix = StaticUtils.getBytes("," +
          currentDN.toNormalizedString());
      byte[] currentDNKey = JebFormat.dnToDNKey(currentDN,
                                               this.baseDN.getNumComponents());
      byte[] suffix = Arrays.copyOf(currentDNKey, currentDNKey.length+1);
      suffix[suffix.length-1] = 0x00;
      /*
       * Set the ending value to a value of equal length but slightly
       * greater than the suffix.
       */
      byte[] end = suffix.clone();
      end[0] = (byte) (end[0] + 1);
      end[end.length-1] = (byte) (end[end.length-1] + 1);
      DatabaseEntry data = new DatabaseEntry();
      DatabaseEntry key = new DatabaseEntry(suffix);
@@ -2983,56 +2997,6 @@
  }
  /**
   * A lexicographic byte array comparator that compares in
   * reverse byte order. This is used for the dn2id database.
   * If we want to find all the entries in a subtree dc=com we know that
   * all subordinate entries must have ,dc=com as a common suffix. In reversing
   * the order of comparison we turn the subtree base into a common prefix
   * and are able to iterate through the keys having that prefix.
   */
  static public class KeyReverseComparator implements Comparator<byte[]>
  {
    /**
     * Compares its two arguments for order.  Returns a negative integer,
     * zero, or a positive integer as the first argument is less than, equal
     * to, or greater than the second.
     *
     * @param a the first object to be compared.
     * @param b the second object to be compared.
     * @return a negative integer, zero, or a positive integer as the
     *         first argument is less than, equal to, or greater than the
     *         second.
     */
    public int compare(byte[] a, byte[] b)
    {
      for (int ai = a.length - 1, bi = b.length - 1;
      ai >= 0 && bi >= 0; ai--, bi--)
      {
        if (a[ai] > b[bi])
        {
          return 1;
        }
        else if (a[ai] < b[bi])
        {
          return -1;
        }
      }
      if (a.length == b.length)
      {
        return 0;
      }
      if (a.length > b.length)
      {
        return 1;
      }
      else
      {
        return -1;
      }
    }
  }
  /**
   * Insert a new entry into the attribute indexes.
   *
   * @param txn The database transaction to be used for the updates.
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ID2Entry.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends.jeb;
import org.opends.messages.Message;
@@ -381,16 +381,11 @@
   * @return true if the entry was written, false if it was not.
   * @throws DatabaseException If an error occurs in the JE database.
   */
  public boolean putRaw(Transaction txn, DatabaseEntry key, DatabaseEntry data)
  public OperationStatus put(Transaction txn, DatabaseEntry key,
                             DatabaseEntry data)
       throws DatabaseException
  {
    OperationStatus status;
    status = put(txn, key, data);
    if (status != OperationStatus.SUCCESS)
    {
      return false;
    }
    return true;
    return super.put(txn, key, data);
  }
  /**
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/JebFormat.java
@@ -22,12 +22,20 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends.jeb;
import static org.opends.server.loggers.debug.DebugLogger.*;
import org.opends.server.loggers.debug.DebugTracer;
import org.opends.server.types.DN;
import org.opends.server.types.RDN;
import org.opends.server.types.ByteStringBuilder;
import org.opends.server.types.DirectoryException;
import org.opends.server.util.StaticUtils;
import java.util.TreeSet;
import java.util.Iterator;
/**
 * Handles the disk representation of LDAP data.
@@ -227,4 +235,138 @@
    return bytes;
  }
  /**
   * Decode a DN value from its database key representation.
   *
   * @param dnKey The database key value of the DN.
   * @param offset Starting position in the database key data.
   * @param length The length of the database key data.
   * @param prefix The DN to prefix the deocded DN value.
   * @return The decoded DN value.
   * @throws DirectoryException if an error occurs while decoding the DN value.
   */
  public static DN dnFromDNKey(byte[] dnKey, int offset, int length, DN prefix)
      throws DirectoryException
  {
    DN dn = prefix;
    int start = offset;
    boolean escaped = false;
    ByteStringBuilder buffer = new ByteStringBuilder();
    for(int i = start; i < length; i++)
    {
      if(dnKey[i] == 0x5C)
      {
        escaped = true;
        continue;
      }
      else if(!escaped && dnKey[i] == 0x01)
      {
        buffer.append(0x01);
        escaped = false;
        continue;
      }
      else if(!escaped && dnKey[i] == 0x00)
      {
        if(buffer.length() > 0)
        {
          dn = dn.concat(RDN.decode(buffer.toString()));
          buffer.clear();
        }
      }
      else
      {
        if(escaped)
        {
          buffer.append(0x5C);
          escaped = false;
        }
        buffer.append(dnKey[i]);
      }
    }
    if(buffer.length() > 0)
    {
      dn = dn.concat(RDN.decode(buffer.toString()));
    }
    return dn;
  }
  /**
   * Find the length of bytes that represents the superior DN of the given
   * DN key. The superior DN is represented by the initial bytes of the DN key.
   *
   * @param dnKey The database key value of the DN.
   * @param offset Starting position in the database key data.
   * @param length The length of the database key data.
   * @return The length of the superior DN or -1 if the given dn is the
   *         root DN or 0 if the superior DN is removed.
   */
  public static int findDNKeyParent(byte[] dnKey, int offset, int length)
  {
    if(length == 0)
    {
      // This is the root or base DN
      return -1;
    }
    // We will walk backwords through the buffer and find the first
    // unescaped comma
    for(int i = offset+length - 1; i >= offset; i--)
    {
      if(dnKey[i] == 0x00 && i-1 >= offset && dnKey[i-1] != 0x5C)
      {
        return i;
      }
    }
    return offset;
  }
  /**
   * Create a DN database key from an entry DN.
   * @param dn The entry DN.
   * @param prefixRDNs The number of prefix RDNs to remove from the encoded
   *                   representation.
   * @return A DatabaseEntry containing the key.
   */
  public static byte[] dnToDNKey(DN dn, int prefixRDNs)
  {
    StringBuilder buffer = new StringBuilder();
    for (int i = dn.getNumComponents() - prefixRDNs - 1; i >= 0; i--)
    {
      buffer.append('\u0000');
      formatRDNKey(dn.getRDN(i), buffer);
    }
    return StaticUtils.getBytes(buffer.toString());
  }
  private static void formatRDNKey(RDN rdn, StringBuilder buffer)
  {
    if (!rdn.isMultiValued())
    {
      rdn.toNormalizedString(buffer);
    }
    else
    {
      TreeSet<String> rdnElementStrings = new TreeSet<String>();
      for (int i=0; i < rdn.getNumValues(); i++)
      {
        StringBuilder b2 = new StringBuilder();
        rdn.getAVAString(i, b2);
        rdnElementStrings.add(b2.toString());
      }
      Iterator<String> iterator = rdnElementStrings.iterator();
      buffer.append(iterator.next().replace("\u0001", "\\\u0001"));
      while (iterator.hasNext())
      {
        buffer.append('\u0001');
        buffer.append(iterator.next().replace("\u0001", "\\\u0001"));
      }
    }
  }
}
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VerifyJob.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends.jeb;
import org.opends.messages.Message;
@@ -575,24 +575,6 @@
      {
        keyCount++;
        DN dn;
        try
        {
          dn = DN.decode(ByteString.wrap(key.getData()));
        }
        catch (DirectoryException e)
        {
          errorCount++;
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
            TRACER.debugError("File dn2id has malformed key %s.%n",
                       StaticUtils.bytesToHex(key.getData()));
          }
          continue;
        }
        EntryID entryID;
        try
        {
@@ -606,7 +588,7 @@
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
            TRACER.debugError("File dn2id has malformed ID for DN <%s>:%n%s%n",
                       dn.toNormalizedString(),
                       new String(key.getData()),
                       StaticUtils.bytesToHex(data.getData()));
          }
          continue;
@@ -633,18 +615,20 @@
          if (debugEnabled())
          {
            TRACER.debugError("File dn2id has DN <%s> referencing unknown " +
                "ID %d%n", dn.toNormalizedString(), entryID.longValue());
                "ID %d%n", new String(key.getData()), entryID.longValue());
          }
        }
        else
        {
          if (!entry.getDN().equals(dn))
          if (!Arrays.equals(JebFormat.dnToDNKey(
              entry.getDN(), verifyConfig.getBaseDN().getNumComponents()),
                             key.getData()))
          {
            errorCount++;
            if (debugEnabled())
            {
              TRACER.debugError("File dn2id has DN <%s> referencing entry " +
                  "with wrong DN <%s>%n", dn.toNormalizedString(),
                  "with wrong DN <%s>%n", new String(key.getData()),
                                          entry.getDN().toNormalizedString());
            }
          }
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java
@@ -95,10 +95,6 @@
  //The DN attribute type.
  private static AttributeType dnType;
  //Comparators for DN and indexes respectively.
  private static final IndexBuffer.DNComparator dnComparator
          = new IndexBuffer.DNComparator();
  private static final IndexBuffer.IndexComparator indexComparator =
          new IndexBuffer.IndexComparator();
@@ -1133,8 +1129,8 @@
                  entryContainer.getDN2ID().getComparator();
          try {
            for(DN excludedDN : suffix.getExcludeBranches()) {
              byte[] bytes =
                      StaticUtils.getBytes(excludedDN.toNormalizedString());
              byte[] bytes = JebFormat.dnToDNKey(
                  excludedDN, suffix.getBaseDN().getNumComponents());
              key.setData(bytes);
              status = cursor.getSearchKeyRange(key, data, lockMode);
              if(status == OperationStatus.SUCCESS &&
@@ -1142,9 +1138,8 @@
                // This is the base entry for a branch that was excluded in the
                // import so we must migrate all entries in this branch over to
                // the new entry container.
                byte[] end = StaticUtils.getBytes("," +
                                excludedDN.toNormalizedString());
                end[0] = (byte) (end[0] + 1);
                byte[] end = Arrays.copyOf(bytes, bytes.length+1);
                end[end.length-1] = 0x01;
                while(status == OperationStatus.SUCCESS &&
                      comparator.compare(key.getData(), end) < 0 &&
@@ -1190,6 +1185,17 @@
    public Void call() throws Exception
    {
      for(Suffix suffix : dnSuffixMap.values()) {
        List<byte[]> includeBranches =
            new ArrayList<byte[]>(suffix.getIncludeBranches().size());
        for(DN includeBranch : suffix.getIncludeBranches())
        {
          if(includeBranch.isDescendantOf(suffix.getBaseDN()))
          {
            includeBranches.add(JebFormat.dnToDNKey(
                includeBranch, suffix.getBaseDN().getNumComponents()));
          }
        }
        EntryContainer entryContainer = suffix.getSrcEntryContainer();
        if(entryContainer != null &&
                !suffix.getIncludeBranches().isEmpty()) {
@@ -1207,8 +1213,17 @@
            status = cursor.getFirst(key, data, lockMode);
            while(status == OperationStatus.SUCCESS &&
                    !importConfiguration.isCancelled() && !isPhaseOneCanceled) {
              DN dn = DN.decode(ByteString.wrap(key.getData()));
              if(!suffix.getIncludeBranches().contains(dn)) {
              boolean found = false;
              for(byte[] includeBranch : includeBranches)
              {
                if(Arrays.equals(includeBranch, key.getData()))
                {
                  found = true;
                  break;
                }
              }
              if(!found) {
                EntryID id = new EntryID(data);
                Entry entry =
                        entryContainer.getID2Entry().get(null,
@@ -1231,9 +1246,8 @@
                 * (the comma).
                 * No possibility of overflow here.
                 */
                byte[] begin =
                        StaticUtils.getBytes("," + dn.toNormalizedString());
                begin[0] = (byte) (begin[0] + 1);
                byte[] begin = Arrays.copyOf(key.getData(), key.getSize()+1);
                begin[begin.length-1] = 0x01;
                key.setData(begin);
                status = cursor.getSearchKeyRange(key, data, lockMode);
              }
@@ -1647,14 +1661,7 @@
          IndexBuffer indexBuffer = e.getValue();
          setIterator.remove();
          ImportIndexType indexType = indexKey.getIndexType();
          if(indexType.equals(ImportIndexType.DN))
          {
            indexBuffer.setComparator(dnComparator);
          }
          else
          {
            indexBuffer.setComparator(indexComparator);
          }
          indexBuffer.setComparator(indexComparator);
          indexBuffer.setIndexKey(indexKey);
          indexBuffer.setDiscard();
          Future<Void> future =
@@ -1717,9 +1724,10 @@
    void processDN2ID(Suffix suffix, DN dn, EntryID entryID)
            throws ConfigException, InterruptedException
    {
      DatabaseContainer dn2id = suffix.getDN2ID();
      byte[] dnBytes = StaticUtils.getBytes(dn.toNormalizedString());
      int id = processKey(dn2id, dnBytes, entryID, dnComparator,
      DN2ID dn2id = suffix.getDN2ID();
      byte[] dnBytes =
          JebFormat.dnToDNKey(dn, suffix.getBaseDN().getNumComponents());
      int id = processKey(dn2id, dnBytes, entryID, indexComparator,
                 new IndexKey(dnType, ImportIndexType.DN, 1), true);
      idECMap.putIfAbsent(id, suffix.getEntryContainer());
    }
@@ -1975,11 +1983,10 @@
    {
      private final int DN_STATE_CACHE_SIZE = 64 * KB;
      private DN parentDN, lastDN;
      private ByteBuffer parentDN, lastDN;
      private EntryID parentID, lastID, entryID;
      private final DatabaseEntry DNKey, DNValue;
      private final TreeMap<DN, EntryID> parentIDMap =
                    new TreeMap<DN, EntryID>();
      private final TreeMap<ByteBuffer, EntryID> parentIDMap;
      private final EntryContainer entryContainer;
      private final Map<byte[], ImportIDSet> id2childTree;
      private final Map<byte[], ImportIDSet> id2subtreeTree;
@@ -1990,6 +1997,7 @@
      DNState(EntryContainer entryContainer)
      {
        this.entryContainer = entryContainer;
        parentIDMap = new TreeMap<ByteBuffer, EntryID>();
        Comparator<byte[]> childComparator =
                entryContainer.getID2Children().getComparator();
        id2childTree = new TreeMap<byte[], ImportIDSet>(childComparator);
@@ -2002,80 +2010,124 @@
        id2subtreeTree =  new TreeMap<byte[], ImportIDSet>(subComparator);
        DNKey = new DatabaseEntry();
        DNValue = new DatabaseEntry();
        lastDN = ByteBuffer.allocate(BYTE_BUFFER_CAPACITY);
      }
      private ByteBuffer getParent(ByteBuffer buffer)
      {
        int parentIndex =
            JebFormat.findDNKeyParent(buffer.array(), 0, buffer.limit());
        if(parentIndex < 0)
        {
          // This is the root or base DN
          return null;
        }
        ByteBuffer parent = buffer.duplicate();
        parent.limit(parentIndex);
        return parent;
      }
      private ByteBuffer deepCopy(ByteBuffer srcBuffer, ByteBuffer destBuffer)
      {
        if(destBuffer == null ||
           destBuffer.clear().remaining() < srcBuffer.limit())
        {
          byte[] bytes = new byte[srcBuffer.limit()];
          System.arraycopy(srcBuffer.array(), 0, bytes, 0,
                           srcBuffer.limit());
          return ByteBuffer.wrap(bytes);
        }
        else
        {
          destBuffer.put(srcBuffer);
          destBuffer.flip();
          return destBuffer;
        }
      }
      // Why do we still need this if we are checking parents in the first
      // phase?
      private boolean checkParent(ImportIDSet record) throws DirectoryException,
              DatabaseException
      {
        DN dn = DN.decode(new String(record.getKey().array(), 0 ,
                                     record.getKey().limit()));
        DNKey.setData(record.getKey().array(), 0 , record.getKey().limit());
        byte[] v = record.toDatabase();
        long v1 = JebFormat.entryIDFromDatabase(v);
        DNValue.setData(v);
        entryID = new EntryID(v1);
        parentDN = getParent(record.getKey());
        //Bypass the cache for append data, lookup the parent in DN2ID and
        //return.
        if(importConfiguration != null &&
           importConfiguration.appendToExistingData())
        {
          parentDN = entryContainer.getParentWithinBase(dn);
          //If null is returned than this is a suffix DN.
          if(parentDN != null)
          {
            parentID =
                entryContainer.getDN2ID().get(null, parentDN, LockMode.DEFAULT);
            DatabaseEntry key = new DatabaseEntry(parentDN.array());
            DatabaseEntry value = new DatabaseEntry();
            OperationStatus status;
            status =
                entryContainer.getDN2ID().read(null, key, value,
                                               LockMode.DEFAULT);
            if(status == OperationStatus.SUCCESS)
            {
              parentID = new EntryID(value);
            }
            else
            {
              // We have a missing parent. Maybe parent checking was turned off?
              // Just ignore.
              parentID = null;
              return false;
            }
          }
        }
        else
        {
          if(parentIDMap.isEmpty())
          {
            parentIDMap.put(dn, entryID);
            parentIDMap.put(deepCopy(record.getKey(), null), entryID);
            return true;
          }
          else if(lastDN != null && lastDN.isAncestorOf(dn))
          else if(lastDN != null && lastDN.equals(parentDN))
          {
            parentIDMap.put(lastDN, lastID);
            parentDN = lastDN;
            parentIDMap.put(deepCopy(lastDN, null), lastID);
            parentID = lastID;
            lastDN = dn;
            lastDN = deepCopy(record.getKey(), lastDN);
            lastID = entryID;
            return true;
          }
          else if(parentIDMap.lastKey().isAncestorOf(dn))
          else if(parentIDMap.lastKey().equals(parentDN))
          {
            parentDN = parentIDMap.lastKey();
            parentID = parentIDMap.get(parentDN);
            lastDN = dn;
            lastDN = deepCopy(record.getKey(), lastDN);
            lastID = entryID;
            return true;
          }
          else
          {
            DN newParentDN = entryContainer.getParentWithinBase(dn);
            if(parentIDMap.containsKey(newParentDN))
            if(parentIDMap.containsKey(parentDN))
            {
              EntryID newParentID = parentIDMap.get(newParentDN);
              DN lastDN = parentIDMap.lastKey();
              while(!newParentDN.equals(lastDN)) {
                parentIDMap.remove(lastDN);
                lastDN = parentIDMap.lastKey();
              EntryID newParentID = parentIDMap.get(parentDN);
              ByteBuffer key = parentIDMap.lastKey();
              while(!parentDN.equals(key)) {
                parentIDMap.remove(key);
                key = parentIDMap.lastKey();
              }
              parentIDMap.put(dn, entryID);
              parentDN = newParentDN;
              parentIDMap.put(deepCopy(record.getKey(), null), entryID);
              parentID = newParentID;
              lastDN = dn;
              lastDN = deepCopy(record.getKey(), lastDN);
              lastID = entryID;
            }
            else
            {
              Message message =
                      NOTE_JEB_IMPORT_LDIF_DN_NO_PARENT.get(dn.toString());
              Entry e = new Entry(dn, null, null, null);
              reader.rejectEntry(e, message);
              // We have a missing parent. Maybe parent checking was turned off?
              // Just ignore.
              parentID = null;
              return false;
            }
          }
@@ -2105,7 +2157,7 @@
      }
      private EntryID getParentID(DN dn) throws DatabaseException
      private EntryID getParentID(ByteBuffer dn) throws DatabaseException
      {
        EntryID nodeID;
        //Bypass the cache for append data, lookup the parent DN in the DN2ID
@@ -2113,7 +2165,20 @@
        if (importConfiguration != null &&
            importConfiguration.appendToExistingData())
        {
          nodeID = entryContainer.getDN2ID().get(null, dn, LockMode.DEFAULT);
            DatabaseEntry key = new DatabaseEntry(dn.array());
            DatabaseEntry value = new DatabaseEntry();
            OperationStatus status;
            status =
                entryContainer.getDN2ID().read(null, key, value,
                                               LockMode.DEFAULT);
            if(status == OperationStatus.SUCCESS)
            {
              nodeID = new EntryID(value);
            }
            else
            {
              nodeID = null;
            }
        }
        else
        {
@@ -2137,8 +2202,10 @@
          idSet = id2subtreeTree.get(parentID.getDatabaseEntry().getData());
        }
        idSet.addEntryID(childID);
        for (DN dn = entryContainer.getParentWithinBase(parentDN); dn != null;
             dn = entryContainer.getParentWithinBase(dn))
        // TODO:
        //  Instead of doing this, we can just walk to parent cache if available
        for (ByteBuffer dn = getParent(parentDN); dn != null;
             dn = getParent(dn))
        {
          EntryID nodeID = getParentID(dn);
          if(nodeID == null)
@@ -2167,7 +2234,7 @@
      public void writeToDB() throws DatabaseException, DirectoryException
      {
        entryContainer.getDN2ID().putRaw(null, DNKey, DNValue);
        entryContainer.getDN2ID().put(null, DNKey, DNValue);
        indexMgr.addTotDNCount(1);
        if(parentDN != null)
        {
@@ -2850,16 +2917,8 @@
      {
        getIndexID();
      }
      if(indexMgr.isDN2ID())
      {
        rc = dnComparator.compare(keyBuf.array(), 0, keyBuf.limit(),
                                 cKey.array(), cKey.limit());
      }
      else
      {
        rc = indexComparator.compare(keyBuf.array(), 0, keyBuf.limit(),
      rc = indexComparator.compare(keyBuf.array(), 0, keyBuf.limit(),
                                     cKey.array(), cKey.limit());
      }
      if(rc != 0) {
        returnCode = 1;
      }
@@ -2888,16 +2947,8 @@
      int returnCode;
      byte[] oKey = o.getKeyBuf().array();
      int oLen = o.getKeyBuf().limit();
      if(indexMgr.isDN2ID())
      {
        returnCode = dnComparator.compare(keyBuf.array(), 0, keyBuf.limit(),
                                          oKey, oLen);
      }
      else
      {
        returnCode = indexComparator.compare(keyBuf.array(), 0, keyBuf.limit(),
      returnCode = indexComparator.compare(keyBuf.array(), 0, keyBuf.limit(),
                                             oKey, oLen);
      }
      if(returnCode == 0)
      {
        if(indexID.intValue() == o.getIndexID().intValue())
@@ -4772,7 +4823,7 @@
      {
        int pLen = PackedInteger.getReadIntLength(bytes, pos);
        len =  PackedInteger.readInt(bytes, pos);
        if(dnComparator.compare(bytes, pos + pLen, len, dnBytes,
        if(indexComparator.compare(bytes, pos + pLen, len, dnBytes,
                dnBytes.length) == 0)
        {
          return true;
opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/IndexBuffer.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2009 Sun Microsystems, Inc.
 *      Copyright 2009-2010 Sun Microsystems, Inc.
 */
@@ -796,172 +796,6 @@
  /**
   * Implementation of ComparatorBuffer interface. Used to compare keys when
   * they are DN index is being processed.
   */
  public static
  class DNComparator implements IndexBuffer.ComparatorBuffer<byte[]>
  {
    /**
     * Compare two offsets in an byte array using the DN compare algorithm.
     * The specified index ID is used in the comparision if the byte arrays
     * are equal.
     *
     * @param b The byte array.
     * @param offset The first offset.
     * @param length The first length.
     * @param indexID The first index id.
     * @param otherOffset The second offset.
     * @param otherLength The second length.
     * @param otherIndexID The second index id.
     * @return a negative integer, zero, or a positive integer as the first
     *         offset value is less than, equal to, or greater than the second.
     */
    public int compare(byte[] b, int offset, int length, int indexID,
                       int otherOffset, int otherLength, int otherIndexID)
    {
      for (int i = length - 1, j = otherLength - 1;
           i >= 0 && j >= 0; i--, j--) {
        if (b[offset + i] > b[otherOffset + j])
        {
          return 1;
        }
        else if (b[offset + i] < b[otherOffset + j])
        {
          return -1;
        }
      }
      //The arrays are equal, make sure they are in the same index since
      //multiple suffixes might have the same key.
      if(length == otherLength)
      {
        if(indexID == otherIndexID)
        {
          return 0;
        }
        else if(indexID > otherIndexID)
        {
          return 1;
        }
        else
        {
          return -1;
        }
      }
      if(length > otherLength)
      {
        return 1;
      }
      else
      {
        return -1;
      }
    }
    /**
     * Compare an offset in an byte array with the specified byte array,
     * using the DN compare algorithm. The specified index ID is used in the
     * comparision if the byte arrays are equal.
     *
     * @param b The byte array.
     * @param offset The first offset.
     * @param length The first length.
     * @param indexID The first index id.
     * @param other The second byte array to compare to.
     * @param otherLength The second object's length.
     * @param otherIndexID The second index id.
     * @return a negative integer, zero, or a positive integer as the first
     *         offset value is less than, equal to, or greater than the second
     *         byte array.
     */
    public int compare(byte[] b, int offset, int length, int indexID,
                       byte[]other, int otherLength, int otherIndexID)
    {
      for (int i = length - 1, j = otherLength - 1;
           i >= 0 && j >= 0; i--, j--) {
        if (b[offset + i] > other[j])
        {
          return 1;
        }
        else if (b[offset + i] < other[j])
        {
          return -1;
        }
      }
     //The arrays are equal, make sure they are in the same index since
      //multiple suffixes might have the same key.
      if(length == otherLength)
      {
        if(indexID == otherIndexID)
        {
          return 0;
        }
        else if(indexID > otherIndexID)
        {
          return 1;
        }
        else
        {
          return -1;
        }
      }
      if(length > otherLength)
      {
        return 1;
      }
      else
      {
        return -1;
      }
    }
    /**
     * Compare an offset in an byte array with the specified byte array,
     * using the DN compare algorithm.
     *
     * @param b The byte array.
     * @param offset The first offset.
     * @param length The first length.
     * @param other The second byte array to compare to.
     * @param otherLength The second object's length.
     * @return a negative integer, zero, or a positive integer as the first
     *         offset value is less than, equal to, or greater than the
     *         second byte array.
     */
    public int compare(byte[] b, int offset, int length, byte[] other,
                       int otherLength)
    {
      for (int i = length - 1, j = otherLength - 1;
           i >= 0 && j >= 0; i--, j--) {
        if (b[offset + i] > other[j])
        {
          return 1;
        }
        else if (b[offset + i] < other[j])
        {
          return -1;
        }
      }
      if(length == otherLength)
      {
        return 0;
      }
      if(length > otherLength)
      {
        return 1;
      }
      else
      {
        return -1;
      }
    }
  }
  /**
   * Implementation of ComparatorBuffer interface. Used to compare keys when
   * they are non-DN indexes.
   */
  public static
opendj-sdk/opends/src/server/org/opends/server/tools/DBTest.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.tools;
@@ -1161,8 +1161,6 @@
        OperationStatus status;
        Comparator<byte[]> defaultComparator =
            new AttributeIndex.KeyComparator();
        Comparator<byte[]> dnComparator =
            new EntryContainer.KeyReverseComparator();
        byte[] start = null;
        byte[] end = null;
        int minSize = -1;
@@ -1320,14 +1318,14 @@
          {
            if(databaseContainer instanceof DN2ID)
            {
              if(dnComparator.compare(key.getData(), end) > 0)
              if(defaultComparator.compare(key.getData(), end) > 0)
              {
                break;
              }
            }
            else if(databaseContainer instanceof DN2URI)
            {
              if(dnComparator.compare(key.getData(), end) > 0)
              if(defaultComparator.compare(key.getData(), end) > 0)
              {
                break;
              }
@@ -1372,8 +1370,9 @@
              {
                try
                {
                  formatedKey = DN.decode(ByteString.wrap(key.getData())).
                    toNormalizedString();
                  formatedKey = JebFormat.dnFromDNKey(
                      key.getData(), 0, key.getSize(), ec.getBaseDN()).
                      toNormalizedString();
                  keyLabel = INFO_LABEL_DBTEST_ENTRY_DN.get();
                }
                catch(Exception e)
@@ -1411,8 +1410,7 @@
              {
                try
                {
                  formatedKey = DN.decode(ByteString.wrap(
                    key.getData())).toNormalizedString();
                  formatedKey = new String(key.getData());
                  keyLabel = INFO_LABEL_DBTEST_ENTRY_DN.get();
                }
                catch(Exception e)
opendj-sdk/opends/src/server/org/opends/server/types/RDN.java
@@ -1063,25 +1063,7 @@
    if (attributeNames.length == 1)
    {
      buffer.append(
          attributeTypes[0].getNormalizedPrimaryNameOrOID());
      buffer.append('=');
      try
      {
        String s = attributeValues[0].getNormalizedValue().toString();
        buffer.append(getDNValue(s));
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        String s = attributeValues[0].getValue().toString();
        buffer.append(getDNValue(s));
      }
      getAVAString(0, buffer);
    }
    else
    {
@@ -1090,26 +1072,7 @@
      for (int i=0; i < attributeNames.length; i++)
      {
        StringBuilder b2 = new StringBuilder();
        b2.append(attributeTypes[i].getNormalizedPrimaryNameOrOID());
        b2.append('=');
        try
        {
          String s =
              attributeValues[i].getNormalizedValue().toString();
          b2.append(getDNValue(s));
        }
        catch (Exception e)
        {
          if (debugEnabled())
          {
            TRACER.debugCaught(DebugLogLevel.ERROR, e);
          }
          String s = attributeValues[i].getValue().toString();
          b2.append(getDNValue(s));
        }
        getAVAString(i, b2);
        rdnElementStrings.add(b2.toString());
      }
@@ -1132,6 +1095,40 @@
  /**
   * Appends a normalized string representation of this RDN to the
   * provided buffer.
   *
   * @param  pos  The position of the attribute type and value to
   *              retrieve.
   * @param  buffer  The buffer to which to append the information.
   */
  public void getAVAString(int pos, StringBuilder buffer)
  {
      buffer.append(
          attributeTypes[pos].getNormalizedPrimaryNameOrOID());
      buffer.append('=');
      try
      {
        String s =
            attributeValues[pos].getNormalizedValue().toString();
        buffer.append(getDNValue(s));
      }
      catch (Exception e)
      {
        if (debugEnabled())
        {
          TRACER.debugCaught(DebugLogLevel.ERROR, e);
        }
        String s = attributeValues[pos].getValue().toString();
        buffer.append(getDNValue(s));
      }
  }
  /**
   * Compares this RDN with the provided RDN based on an alphabetic
   * comparison of the attribute names and values.
   *
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestEntryContainer.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends.jeb;
@@ -52,9 +52,8 @@
  private  String beID="userRoot";
  private BackendImpl be;
  private static final String ldifString = "dn: dc=com\n"
      + "objectClass: top\n" + "objectClass: domain\n" + "\n"
      + "dn: dc=example,dc=com\n" + "objectClass: top\n"
  private static final String ldifString = "dn: dc=example,dc=com\n"
      + "objectClass: top\n"
      + "objectClass: domain\n" + "\n"
      + "dn: ou=People,dc=example,dc=com\n" + "objectClass: top\n"
      + "objectClass: organizationalUnit\n" + "\n"
@@ -72,9 +71,9 @@
      + "telephoneNumber: 216-564-6748\n" + "employeeNumber: 1\n"
      + "sn: Amar\n" + "givenName: Aaccf\n" + "postalCode: 85762\n"
      + "userPassword: password\n" + "initials: AA\n" + "\n"
      + "dn: o=Airius\n" + "objectClass: top\n"
      + "dn: o=Airius,dc=example,dc=com\n" + "objectClass: top\n"
      + "objectClass: organization\n" + "\n"
      + "dn:: b3U95Za25qWt6YOoLG89QWlyaXVz\n"
      + "dn:: b3U95Za25qWt6YOoLG89QWlyaXVzLGRjPWV4YW1wbGUsZGM9Y29t\n"
      + "# dn:: ou=<JapaneseOU>,o=Airius\n" + "objectclass: top\n"
      + "objectclass: organizationalUnit\n" + "ou:: 5Za25qWt6YOo\n"
      + "# ou:: <JapaneseOU>\n" + "ou;lang-ja:: 5Za25qWt6YOo\n"
@@ -82,7 +81,7 @@
      + "ou;lang-ja;phonetic:: 44GI44GE44GO44KH44GG44G2\n"
      + "# ou;lang-ja:: <JapaneseOU_in_phonetic_representation>\n"
      + "ou;lang-en: Sales\n" + "description: Japanese office\n" + "\n"
      + "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVz\n"
      + "dn:: dWlkPXJvZ2FzYXdhcmEsb3U95Za25qWt6YOoLG89QWlyaXVzLGRjPWV4YW1wbGUsZGM9Y29t\n"
      + "# dn:: uid=<uid>,ou=<JapaneseOU>,o=Airius\n"
      + "userpassword: {SHA}O3HSv1MusyL4kTjP+HKI5uxuNoM=\n"
      + "objectclass: top\n" + "objectclass: person\n"
opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
@@ -22,7 +22,7 @@
 * CDDL HEADER END
 *
 *
 *      Copyright 2006-2008 Sun Microsystems, Inc.
 *      Copyright 2006-2010 Sun Microsystems, Inc.
 */
package org.opends.server.backends.jeb;
@@ -228,11 +228,11 @@
           new DatabaseEntry(StaticUtils.getBytes(badDN));
      DatabaseEntry data =
           new EntryID(37).getDatabaseEntry();
      assertTrue(dn2id.putRaw(txn, key, data));
      assertEquals(dn2id.put(txn, key, data), OperationStatus.SUCCESS);
      //Add DN key with malformed entryID
      key=new DatabaseEntry(StaticUtils.getBytes(junkDN2));
      data= new DatabaseEntry(new byte[3]);
      assertTrue(dn2id.putRaw(txn, key, data));
      assertEquals(dn2id.put(txn, key, data), OperationStatus.SUCCESS);
      //Try to break JebFormat version
      addID2EntryReturnKey(junkDN3, 20, true);
      id=new EntryID(20);
@@ -445,7 +445,7 @@
           ID2Entry.entryToDatabase(testEntry,
                                     new DataConfig(false, false, null));
      DatabaseEntry data= new DatabaseEntry(entryBytes.toByteArray());
      assertTrue(id2entry.putRaw(txn, key, data));
      assertEquals(id2entry.put(txn, key, data), OperationStatus.SUCCESS);
      //add entry with ramdom bytes
      DatabaseEntry key1= new EntryID(4).getDatabaseEntry();
@@ -456,7 +456,7 @@
      //set version correctly
      eBytes[0]=0x01;
      DatabaseEntry data1= new DatabaseEntry(eBytes);
      assertTrue(id2entry.putRaw(txn, key1, data1));
      assertEquals(id2entry.put(txn, key1, data1), OperationStatus.SUCCESS);
      performBECompleteVerify("telephoneNumber", 3);
    }
    finally
@@ -778,7 +778,7 @@
    if(trashFormat)
      entryBytes[0] = 0x67;
    DatabaseEntry data= new DatabaseEntry(entryBytes);
    assertTrue(id2entry.putRaw(txn, key, data));
    assertEquals(id2entry.put(txn, key, data), OperationStatus.SUCCESS);
    return key;
  }