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