From 63df1be1c3bd715cec05512c359490290d7265c3 Mon Sep 17 00:00:00 2001
From: abobrov <abobrov@localhost>
Date: Sat, 09 Jun 2007 22:12:02 +0000
Subject: [PATCH] switch to Entry class encode/decode methods and custom encode config.

---
 opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java |  456 +-------------------------------------------------------
 1 files changed, 11 insertions(+), 445 deletions(-)

diff --git a/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java b/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
index 63878b8..abc6f8e 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
+++ b/opendj-sdk/opends/src/server/org/opends/server/extensions/FileSystemEntryCache.java
@@ -30,11 +30,9 @@
 import java.util.HashSet;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.locks.Lock;
 import java.util.Iterator;
-import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.TimeUnit;
@@ -43,7 +41,6 @@
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.atomic.AtomicLong;
-import java.io.UnsupportedEncodingException;
 import java.io.File;
 import com.sleepycat.bind.EntryBinding;
 import com.sleepycat.bind.serial.SerialBinding;
@@ -66,14 +63,10 @@
 import org.opends.server.admin.server.ConfigurationChangeListener;
 import org.opends.server.config.ConfigException;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.protocols.asn1.ASN1Element;
-import org.opends.server.protocols.asn1.ASN1OctetString;
-import org.opends.server.types.Attribute;
-import org.opends.server.types.AttributeType;
-import org.opends.server.types.AttributeValue;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DN;
 import org.opends.server.types.Entry;
+import org.opends.server.types.EntryEncodeConfig;
 import org.opends.server.types.ErrorLogCategory;
 import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
@@ -82,7 +75,6 @@
 import org.opends.server.types.SearchFilter;
 import org.opends.server.types.FilePermission;
 import org.opends.server.types.LockManager;
-import org.opends.server.types.ObjectClass;
 import org.opends.server.types.DebugLogLevel;
 import org.opends.server.loggers.debug.DebugTracer;
 import static org.opends.server.loggers.debug.DebugLogger.*;
@@ -244,6 +236,11 @@
   private long persistentEntriesSaved    = 0;
   private long persistentEntriesRestored = 0;
 
+  // The configuration to use when encoding entries in the database.
+  // TODO: make compression feature configurable.
+  private static EntryEncodeConfig encodeConfig =
+      new EntryEncodeConfig(true, false, false);
+
   /**
    * Creates a new instance of this entry cache.
    */
@@ -1676,7 +1673,9 @@
               primaryData,
               LockMode.DEFAULT) == OperationStatus.SUCCESS) {
 
-        return decodeEntry(entryDN, primaryData.getData());
+        Entry entry = Entry.decode(primaryData.getData());
+        entry.setDN(entryDN);
+        return entry;
       } else {
         throw new Exception();
       }
@@ -1756,7 +1755,8 @@
 
       // Create data and put this cache entry into the database.
       if (entryCacheDB.put(null, cacheEntryKey,
-          new DatabaseEntry(encodeEntry(entry))) == OperationStatus.SUCCESS) {
+          new DatabaseEntry(
+          entry.encode(encodeConfig))) == OperationStatus.SUCCESS) {
 
         // Add the entry to the cache maps.
         dnMap.put(entry.getDN(), entryID);
@@ -1787,440 +1787,6 @@
     }
   }
 
-  /**
-   * TODO: Custom encoding used here due to performance and space
-   * considerations. The caller should use Entry.encode() method,
-   * see Issue 1675.
-   */
-  private static byte[] encodeEntry(Entry entry)
-  {
-    // Encode cache entry.
-    int totalBytes = 0;
-
-    // The object classes will be encoded as one-to-five byte length
-    // followed by a zero-delimited UTF-8 byte representation of the
-    // names (e.g., top\0person\0organizationalPerson\0inetOrgPerson).
-    int i=0;
-    int totalOCBytes = entry.getObjectClasses().size() - 1;
-    byte[][] ocBytes = new byte[entry.getObjectClasses().size()][];
-    for (String ocName : entry.getObjectClasses().values()) {
-      ocBytes[i] = getBytes(ocName);
-      totalOCBytes += ocBytes[i++].length;
-    }
-    byte[] ocLength = ASN1Element.encodeLength(totalOCBytes);
-    totalBytes += totalOCBytes + ocLength.length;
-
-
-    // The user attributes will be encoded as a one-to-five byte
-    // number of attributes followed by a sequence of:
-    // - A UTF-8 byte representation of the attribute name.
-    // - A zero delimiter
-    // - A one-to-five byte number of values for the attribute
-    // - A sequence of:
-    //   - A one-to-five byte length for the value
-    //   - A UTF-8 byte representation for the value
-    i=0;
-    int numUserAttributes = 0;
-    int totalUserAttrBytes = 0;
-    LinkedList<byte[]> userAttrBytes = new LinkedList<byte[]>();
-    for (List<Attribute> attrList :
-      entry.getUserAttributes().values()) {
-      for (Attribute a : attrList) {
-        if (a.isVirtual() || (! a.hasValue())) {
-          continue;
-        }
-
-        numUserAttributes++;
-
-        byte[] nameBytes = getBytes(a.getNameWithOptions());
-
-        int numValues = 0;
-        int totalValueBytes = 0;
-        LinkedList<byte[]> valueBytes = new LinkedList<byte[]>();
-        for (AttributeValue v : a.getValues()) {
-          numValues++;
-          byte[] vBytes = v.getValueBytes();
-          byte[] vLength = ASN1Element.encodeLength(vBytes.length);
-          valueBytes.add(vLength);
-          valueBytes.add(vBytes);
-          totalValueBytes += vLength.length + vBytes.length;
-        }
-        byte[] numValuesBytes = ASN1Element.encodeLength(numValues);
-
-        byte[] attrBytes = new byte[nameBytes.length +
-            numValuesBytes.length +
-            totalValueBytes + 1];
-        System.arraycopy(nameBytes, 0, attrBytes, 0,
-            nameBytes.length);
-
-        int pos = nameBytes.length+1;
-        System.arraycopy(numValuesBytes, 0, attrBytes, pos,
-            numValuesBytes.length);
-        pos += numValuesBytes.length;
-        for (byte[] b : valueBytes) {
-          System.arraycopy(b, 0, attrBytes, pos, b.length);
-          pos += b.length;
-        }
-
-        userAttrBytes.add(attrBytes);
-        totalUserAttrBytes += attrBytes.length;
-      }
-    }
-    byte[] userAttrCount =
-        ASN1OctetString.encodeLength(numUserAttributes);
-    totalBytes += totalUserAttrBytes + userAttrCount.length;
-
-    // The operational attributes will be encoded in the same way as
-    // the user attributes.
-    i=0;
-    int numOperationalAttributes = 0;
-    int totalOperationalAttrBytes = 0;
-    LinkedList<byte[]> operationalAttrBytes =
-        new LinkedList<byte[]>();
-    for (List<Attribute> attrList :
-      entry.getOperationalAttributes().values()) {
-      for (Attribute a : attrList) {
-        if (a.isVirtual() || (! a.hasValue())) {
-          continue;
-        }
-
-        numOperationalAttributes++;
-
-        byte[] nameBytes = getBytes(a.getNameWithOptions());
-
-        int numValues = 0;
-        int totalValueBytes = 0;
-        LinkedList<byte[]> valueBytes = new LinkedList<byte[]>();
-        for (AttributeValue v : a.getValues()) {
-          numValues++;
-          byte[] vBytes = v.getValueBytes();
-          byte[] vLength = ASN1Element.encodeLength(vBytes.length);
-          valueBytes.add(vLength);
-          valueBytes.add(vBytes);
-          totalValueBytes += vLength.length + vBytes.length;
-        }
-        byte[] numValuesBytes = ASN1Element.encodeLength(numValues);
-
-        byte[] attrBytes = new byte[nameBytes.length +
-            numValuesBytes.length +
-            totalValueBytes + 1];
-        System.arraycopy(nameBytes, 0, attrBytes, 0,
-            nameBytes.length);
-
-        int pos = nameBytes.length+1;
-        System.arraycopy(numValuesBytes, 0, attrBytes, pos,
-            numValuesBytes.length);
-        pos += numValuesBytes.length;
-        for (byte[] b : valueBytes) {
-          System.arraycopy(b, 0, attrBytes, pos, b.length);
-          pos += b.length;
-        }
-
-        operationalAttrBytes.add(attrBytes);
-        totalOperationalAttrBytes += attrBytes.length;
-      }
-    }
-    byte[] operationalAttrCount =
-        ASN1OctetString.encodeLength(numOperationalAttributes);
-    totalBytes += totalOperationalAttrBytes +
-        operationalAttrCount.length;
-
-
-    // Now we've got all the data that we need.  Create a big byte
-    // array to hold it all and pack it in.
-    byte[] entryBytes = new byte[totalBytes];
-
-    int pos = 0;
-
-    // Add the object classes length and values.
-    System.arraycopy(ocLength, 0, entryBytes, pos, ocLength.length);
-    pos += ocLength.length;
-    for (byte[] b : ocBytes) {
-      System.arraycopy(b, 0, entryBytes, pos, b.length);
-      pos += b.length + 1;
-    }
-
-    // We need to back up one because there's no zero-teriminator
-    // after the last object class name.
-    pos--;
-
-    // Next, add the user attribute count and the user attribute
-    // data.
-    System.arraycopy(userAttrCount, 0, entryBytes, pos,
-        userAttrCount.length);
-    pos += userAttrCount.length;
-    for (byte[] b : userAttrBytes) {
-      System.arraycopy(b, 0, entryBytes, pos, b.length);
-      pos += b.length;
-    }
-
-    // Finally, add the operational attribute count and the
-    // operational attribute data.
-    System.arraycopy(operationalAttrCount, 0, entryBytes, pos,
-        operationalAttrCount.length);
-    pos += operationalAttrCount.length;
-    for (byte[] b : operationalAttrBytes) {
-      System.arraycopy(b, 0, entryBytes, pos, b.length);
-      pos += b.length;
-    }
-
-    return entryBytes;
-  }
-
-  /**
-   * TODO: Custom decoding used here due to performance and space
-   * considerations. The caller should use Entry.decode() method,
-   * see Issue 1675.
-   */
-  private static Entry decodeEntry(DN entryDN, byte[] entryBytes)
-      throws UnsupportedEncodingException
-  {
-    // Decode cache entry.
-    int pos = 0;
-    // The length of the object classes.  It may be a single
-    // byte or multiple bytes.
-    int ocLength = entryBytes[pos] & 0x7F;
-    if (entryBytes[pos++] != ocLength) {
-      int numLengthBytes = ocLength;
-      ocLength = 0;
-      for (int i=0; i < numLengthBytes; i++, pos++) {
-        ocLength = (ocLength << 8) | (entryBytes[pos] & 0xFF);
-      }
-    }
-
-    // Next is the encoded set of object classes.  It will be a
-    // single string with the object class names separated by zeros.
-    LinkedHashMap<ObjectClass,String> objectClasses =
-        new LinkedHashMap<ObjectClass,String>();
-    int startPos = pos;
-    for (int i=0; i < ocLength; i++,pos++) {
-      if (entryBytes[pos] == 0x00) {
-        String name = new String(entryBytes, startPos, pos-startPos,
-            "UTF-8");
-        String lowerName = toLowerCase(name);
-        ObjectClass oc =
-            DirectoryServer.getObjectClass(lowerName, true);
-        objectClasses.put(oc, name);
-        startPos = pos+1;
-      }
-    }
-    String name = new String(entryBytes, startPos, pos-startPos,
-        "UTF-8");
-    String lowerName = toLowerCase(name);
-    ObjectClass oc =
-        DirectoryServer.getObjectClass(lowerName, true);
-    objectClasses.put(oc, name);
-
-    // Next is the total number of user attributes.  It may be a
-    // single byte or multiple bytes.
-    int numUserAttrs = entryBytes[pos] & 0x7F;
-    if (entryBytes[pos++] != numUserAttrs) {
-      int numLengthBytes = numUserAttrs;
-      numUserAttrs = 0;
-      for (int i=0; i < numLengthBytes; i++, pos++) {
-        numUserAttrs = (numUserAttrs << 8) |
-            (entryBytes[pos] & 0xFF);
-      }
-    }
-
-    // Now, we should iterate through the user attributes and decode
-    // each one.
-    LinkedHashMap<AttributeType,List<Attribute>> userAttributes =
-        new LinkedHashMap<AttributeType,List<Attribute>>();
-    for (int i=0; i < numUserAttrs; i++) {
-      // First, we have the zero-terminated attribute name.
-      startPos = pos;
-      while (entryBytes[pos] != 0x00) {
-        pos++;
-      }
-      name = new String(entryBytes, startPos, pos-startPos,
-          "UTF-8");
-      LinkedHashSet<String> options;
-      int semicolonPos = name.indexOf(';');
-      if (semicolonPos > 0) {
-        String baseName = name.substring(0, semicolonPos);
-        lowerName = toLowerCase(baseName);
-        options   = new LinkedHashSet<String>();
-
-        int nextPos = name.indexOf(';', semicolonPos+1);
-        while (nextPos > 0) {
-          String option = name.substring(semicolonPos+1, nextPos);
-          if (option.length() > 0) {
-            options.add(option);
-          }
-
-          semicolonPos = nextPos;
-          nextPos = name.indexOf(';', semicolonPos+1);
-        }
-
-        String option = name.substring(semicolonPos+1);
-        if (option.length() > 0) {
-          options.add(option);
-        }
-
-        name = baseName;
-      } else {
-        lowerName = toLowerCase(name);
-        options   = new LinkedHashSet<String>(0);
-      }
-      AttributeType attributeType =
-          DirectoryServer.getAttributeType(lowerName, true);
-
-      // Next, we have the number of values.
-      int numValues = entryBytes[++pos] & 0x7F;
-      if (entryBytes[pos++] != numValues) {
-        int numLengthBytes = numValues;
-        numValues = 0;
-        for (int j=0; j < numLengthBytes; j++, pos++) {
-          numValues = (numValues << 8) | (entryBytes[pos] & 0xFF);
-        }
-      }
-
-      // Next, we have the sequence of length-value pairs.
-      LinkedHashSet<AttributeValue> values =
-          new LinkedHashSet<AttributeValue>(numValues);
-      for (int j=0; j < numValues; j++) {
-        int valueLength = entryBytes[pos] & 0x7F;
-        if (entryBytes[pos++] != valueLength) {
-          int numLengthBytes = valueLength;
-          valueLength = 0;
-          for (int k=0; k < numLengthBytes; k++, pos++) {
-            valueLength = (valueLength << 8) |
-                (entryBytes[pos] & 0xFF);
-          }
-        }
-
-        byte[] valueBytes = new byte[valueLength];
-        System.arraycopy(entryBytes, pos, valueBytes, 0,
-            valueLength);
-        values.add(new AttributeValue(attributeType,
-            new ASN1OctetString(valueBytes)));
-        pos += valueLength;
-      }
-
-      // Create the attribute and add it to the set of user
-      // attributes.
-      Attribute a = new Attribute(attributeType, name, options,
-          values);
-      List<Attribute> attrList = userAttributes.get(attributeType);
-      if (attrList == null) {
-        attrList = new ArrayList<Attribute>(1);
-        attrList.add(a);
-        userAttributes.put(attributeType, attrList);
-      } else {
-        attrList.add(a);
-      }
-    }
-
-    // Next is the total number of operational attributes.  It may
-    // be a single byte or multiple bytes.
-    int numOperationalAttrs = entryBytes[pos] & 0x7F;
-    if (entryBytes[pos++] != numOperationalAttrs) {
-      int numLengthBytes = numOperationalAttrs;
-      numOperationalAttrs = 0;
-      for (int i=0; i < numLengthBytes; i++, pos++) {
-        numOperationalAttrs =
-            (numOperationalAttrs << 8) | (entryBytes[pos] & 0xFF);
-      }
-    }
-
-    // Now, we should iterate through the operational attributes and
-    // decode each one.
-    LinkedHashMap<AttributeType,List<Attribute>>
-        operationalAttributes =
-        new LinkedHashMap<AttributeType,List<Attribute>>();
-    for (int i=0; i < numOperationalAttrs; i++) {
-      // First, we have the zero-terminated attribute name.
-      startPos = pos;
-      while (entryBytes[pos] != 0x00) {
-        pos++;
-      }
-      name = new String(entryBytes, startPos, pos-startPos,
-          "UTF-8");
-      LinkedHashSet<String> options;
-      int semicolonPos = name.indexOf(';');
-      if (semicolonPos > 0) {
-        String baseName = name.substring(0, semicolonPos);
-        lowerName = toLowerCase(baseName);
-        options   = new LinkedHashSet<String>();
-
-        int nextPos = name.indexOf(';', semicolonPos+1);
-        while (nextPos > 0) {
-          String option = name.substring(semicolonPos+1, nextPos);
-          if (option.length() > 0) {
-            options.add(option);
-          }
-
-          semicolonPos = nextPos;
-          nextPos = name.indexOf(';', semicolonPos+1);
-        }
-
-        String option = name.substring(semicolonPos+1);
-        if (option.length() > 0) {
-          options.add(option);
-        }
-
-        name = baseName;
-      } else {
-        lowerName = toLowerCase(name);
-        options   = new LinkedHashSet<String>(0);
-      }
-      AttributeType attributeType =
-          DirectoryServer.getAttributeType(lowerName, true);
-
-      // Next, we have the number of values.
-      int numValues = entryBytes[++pos] & 0x7F;
-      if (entryBytes[pos++] != numValues) {
-        int numLengthBytes = numValues;
-        numValues = 0;
-        for (int j=0; j < numLengthBytes; j++, pos++) {
-          numValues = (numValues << 8) | (entryBytes[pos] & 0xFF);
-        }
-      }
-
-      // Next, we have the sequence of length-value pairs.
-      LinkedHashSet<AttributeValue> values =
-          new LinkedHashSet<AttributeValue>(numValues);
-      for (int j=0; j < numValues; j++) {
-        int valueLength = entryBytes[pos] & 0x7F;
-        if (entryBytes[pos++] != valueLength) {
-          int numLengthBytes = valueLength;
-          valueLength = 0;
-          for (int k=0; k < numLengthBytes; k++, pos++) {
-            valueLength = (valueLength << 8) |
-                (entryBytes[pos] & 0xFF);
-          }
-        }
-
-        byte[] valueBytes = new byte[valueLength];
-        System.arraycopy(entryBytes, pos, valueBytes, 0,
-            valueLength);
-        values.add(new AttributeValue(attributeType,
-            new ASN1OctetString(valueBytes)));
-        pos += valueLength;
-      }
-
-      // Create the attribute and add it to the set of operational
-      // attributes.
-      Attribute a = new Attribute(attributeType, name, options,
-          values);
-      List<Attribute> attrList =
-          operationalAttributes.get(attributeType);
-      if (attrList == null) {
-        attrList = new ArrayList<Attribute>(1);
-        attrList.add(a);
-        operationalAttributes.put(attributeType, attrList);
-      } else {
-        attrList.add(a);
-      }
-    }
-
-    // We've got everything that we need, so create and return the
-    // entry.
-    return new
-        Entry(entryDN, objectClasses, userAttributes, operationalAttributes);
-  }
-
  /**
   * Checks if the cache home exist and if not tries to recursively create it.
   * If either is successful adjusts cache home access permissions accordingly

--
Gitblit v1.10.0