From 31a3bbd4e956110d2bd6107866cf774f4da340b5 Mon Sep 17 00:00:00 2001
From: ludovicp <ludovicp@localhost>
Date: Fri, 25 Jun 2010 09:40:08 +0000
Subject: [PATCH] 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.

---
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ID2Entry.java                                   |   13 
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java                             |  110 ++----
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VerifyJob.java                                  |   30 -
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java                        |  209 ++++++++----
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2ID.java                                      |   73 ++-
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/IndexBuffer.java                     |  168 ----------
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java      |   12 
 opendj-sdk/opends/src/server/org/opends/server/tools/DBTest.java                                            |   16 
 opendj-sdk/opends/src/server/org/opends/server/types/RDN.java                                               |   75 ++--
 opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestEntryContainer.java |   13 
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/JebFormat.java                                  |  144 ++++++++
 opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2URI.java                                     |   60 +--
 12 files changed, 446 insertions(+), 477 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2ID.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2ID.java
index c0f2825..ac3bf3b 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2ID.java
+++ b/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;
   }
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2URI.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2URI.java
index fbd5db1..5f32559 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/DN2URI.java
+++ b/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;
-  }
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
index f991b2c..8e05b20 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/EntryContainer.java
+++ b/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.
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ID2Entry.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ID2Entry.java
index 0f55969..0a7c242 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/ID2Entry.java
+++ b/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);
   }
 
   /**
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/JebFormat.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/JebFormat.java
index c9f375d..34f0692 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/JebFormat.java
+++ b/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"));
+      }
+    }
+  }
 }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VerifyJob.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VerifyJob.java
index bc97f5b..28f70ea 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/VerifyJob.java
+++ b/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());
             }
           }
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java
index e2064cc..4453e79 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/Importer.java
+++ b/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;
diff --git a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/IndexBuffer.java b/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/IndexBuffer.java
index 0b87116..992ecc8 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/backends/jeb/importLDIF/IndexBuffer.java
+++ b/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
diff --git a/opendj-sdk/opends/src/server/org/opends/server/tools/DBTest.java b/opendj-sdk/opends/src/server/org/opends/server/tools/DBTest.java
index 5bf9364..b24a540 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/tools/DBTest.java
+++ b/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)
diff --git a/opendj-sdk/opends/src/server/org/opends/server/types/RDN.java b/opendj-sdk/opends/src/server/org/opends/server/types/RDN.java
index 247e09b..6b99b10 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/types/RDN.java
+++ b/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.
    *
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestEntryContainer.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestEntryContainer.java
index dd4fe8c..f8a3736 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestEntryContainer.java
+++ b/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"
diff --git a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java b/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
index b912076..eda63a3 100644
--- a/opendj-sdk/opends/tests/unit-tests-testng/src/server/org/opends/server/backends/jeb/TestVerifyJob.java
+++ b/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;
   }
 

--
Gitblit v1.10.0