You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by ju...@apache.org on 2010/10/15 16:30:22 UTC
svn commit: r1022942 - in
/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util:
BundleBinding.java BundleReader.java BundleWriter.java
Author: jukka
Date: Fri Oct 15 14:30:22 2010
New Revision: 1022942
URL: http://svn.apache.org/viewvc?rev=1022942&view=rev
Log:
JCR-2762: Optimize bundle serialization
Use a bit field to optimize for common mixin type, property, child node, and shared set counts.
Modified:
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleBinding.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java
jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleWriter.java
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleBinding.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleBinding.java?rev=1022942&r1=1022941&r2=1022942&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleBinding.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleBinding.java Fri Oct 15 14:30:22 2010
@@ -34,12 +34,12 @@ public class BundleBinding {
static final int BINARY_IN_DATA_STORE = -2;
/**
- * A special UUID used to mark a <code>null</code> {@link NodeId} value.
- * This is a proper type 1 UUID to prevent collisions with other
- * identifiers, even special non-random ones like
+ * A special UUID used to mark the <code>null</code> parent identifier
+ * of the root node. This is a proper type 1 UUID to prevent collisions
+ * with other identifiers, even special non-random ones like
* <code>00000000-0000-0000-0000-000000000000</code>.
*/
- static final NodeId NULL_NODE_ID =
+ static final NodeId NULL_PARENT_ID =
new NodeId("bb4e9d10-d857-11df-937b-0800200c9a66");
/**
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java?rev=1022942&r1=1022941&r2=1022942&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleReader.java Fri Oct 15 14:30:22 2010
@@ -16,8 +16,6 @@
*/
package org.apache.jackrabbit.core.persistence.util;
-import static org.apache.jackrabbit.core.persistence.util.BundleBinding.NULL_NODE_ID;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.jackrabbit.core.id.NodeId;
@@ -127,152 +125,149 @@ class BundleReader {
*/
public NodePropBundle readBundle(NodeId id) throws IOException {
NodePropBundle bundle = new NodePropBundle(id);
-
- // read primary type...special handling
- Name nodeTypeName;
if (version >= BundleBinding.VERSION_3) {
- nodeTypeName = readName();
+ readBundleNew(bundle);
} else {
- int a = in.readUnsignedByte();
- int b = in.readUnsignedByte();
- int c = in.readUnsignedByte();
- String uri = binding.nsIndex.indexToString(a << 16 | b << 8 | c);
- String local = binding.nameIndex.indexToString(in.readInt());
- nodeTypeName = NameFactoryImpl.getInstance().create(uri, local);
+ readBundleOld(bundle);
}
- bundle.setNodeTypeName(nodeTypeName);
+ return bundle;
+ }
- // parentUUID
- bundle.setParentId(readNodeId());
+ private void readBundleNew(NodePropBundle bundle) throws IOException {
+ // node type
+ bundle.setNodeTypeName(readName());
- if (version < BundleBinding.VERSION_3) {
- // definitionId
- in.readUTF();
+ // parentUUID
+ NodeId parentId = readNodeId();
+ if (BundleBinding.NULL_PARENT_ID.equals(parentId)) {
+ parentId = null;
}
+ bundle.setParentId(parentId);
- // mixin types
- readMixinTypes(bundle);
-
- // properties
- readProperties(bundle);
-
- // set referenceable flag
- bundle.setReferenceable(in.readBoolean());
+ // read modcount
+ bundle.setModCount((short) readVarInt());
- // child nodes (list of uuid/name pairs)
- readChildNodeEntries(bundle);
+ int b = in.readUnsignedByte();
+ bundle.setReferenceable((b & 1) != 0);
- // read modcount, since version 1.0
- if (version >= BundleBinding.VERSION_3) {
- bundle.setModCount((short) readVarInt());
- } else if (version >= BundleBinding.VERSION_1) {
- bundle.setModCount(in.readShort());
+ // mixin types
+ int mn = readVarInt((b >> 7) & 1, 1);
+ if (mn == 0) {
+ bundle.setMixinTypeNames(Collections.<Name>emptySet());
+ } else if (mn == 1) {
+ bundle.setMixinTypeNames(Collections.singleton(readName()));
+ } else {
+ Set<Name> mixins = new HashSet<Name>(mn * 2);
+ for (int i = 0; i < mn; i++) {
+ mixins.add(readName());
+ }
+ bundle.setMixinTypeNames(mixins);
}
- // read shared set, since version 2.0
- readSharedSet(bundle);
+ // properties
+ int pn = readVarInt((b >> 4) & 7, 7);
+ for (int i = 0; i < pn; i++) {
+ PropertyId id = new PropertyId(bundle.getId(), readName());
+ bundle.addProperty(readPropertyEntry(id));
+ }
- return bundle;
- }
+ // child nodes (list of name/uuid pairs)
+ int nn = readVarInt((b >> 2) & 3, 3);
+ for (int i = 0; i < nn; i++) {
+ Name name = readQName();
+ NodeId id = readNodeId();
+ bundle.addChildNodeEntry(name, id);
+ }
- private void readMixinTypes(NodePropBundle bundle) throws IOException {
- if (version >= BundleBinding.VERSION_3) {
- int n = readVarInt();
- if (n == 0) {
- bundle.setMixinTypeNames(Collections.<Name>emptySet());
- } else if (n == 1) {
- bundle.setMixinTypeNames(Collections.singleton(readName()));
- } else {
- Set<Name> mixins = new HashSet<Name>(n * 2);
- for (int i = 0; i < n; i++) {
- mixins.add(readName());
- }
- bundle.setMixinTypeNames(mixins);
- }
+ // read shared set
+ int sn = readVarInt((b >> 1) & 1, 1);
+ if (sn == 0) {
+ bundle.setSharedSet(Collections.<NodeId>emptySet());
+ } else if (sn == 1) {
+ bundle.setSharedSet(Collections.singleton(readNodeId()));
} else {
- Name name = readIndexedQName();
- if (name == null) {
- bundle.setMixinTypeNames(Collections.<Name>emptySet());
- } else {
- Set<Name> mixinTypeNames = new HashSet<Name>();
- do {
- mixinTypeNames.add(name);
- name = readIndexedQName();
- } while (name != null);
- bundle.setMixinTypeNames(mixinTypeNames);
+ Set<NodeId> shared = new HashSet<NodeId>();
+ for (int i = 0; i < sn; i++) {
+ shared.add(readNodeId());
}
+ bundle.setSharedSet(shared);
}
}
- private void readProperties(NodePropBundle bundle) throws IOException {
- if (version >= BundleBinding.VERSION_3) {
- int n = readVarInt();
- for (int i = 0; i < n; i++) {
- PropertyId id = new PropertyId(bundle.getId(), readName());
- bundle.addProperty(readPropertyEntry(id));
- }
- } else {
- Name name = readIndexedQName();
- while (name != null) {
- PropertyId pId = new PropertyId(bundle.getId(), name);
- NodePropBundle.PropertyEntry pState = readPropertyEntry(pId);
- // skip redundant primaryType, mixinTypes and uuid properties
- if (!name.equals(NameConstants.JCR_PRIMARYTYPE)
- && !name.equals(NameConstants.JCR_MIXINTYPES)
- && !name.equals(NameConstants.JCR_UUID)) {
- bundle.addProperty(pState);
- }
+ private void readBundleOld(NodePropBundle bundle) throws IOException {
+ // read primary type...special handling
+ int a = in.readUnsignedByte();
+ int b = in.readUnsignedByte();
+ int c = in.readUnsignedByte();
+ String uri = binding.nsIndex.indexToString(a << 16 | b << 8 | c);
+ String local = binding.nameIndex.indexToString(in.readInt());
+ bundle.setNodeTypeName(
+ NameFactoryImpl.getInstance().create(uri, local));
+
+ // parentUUID
+ bundle.setParentId(readNodeId());
+
+ // definitionId
+ in.readUTF();
+
+ // mixin types
+ Name name = readIndexedQName();
+ if (name != null) {
+ Set<Name> mixinTypeNames = new HashSet<Name>();
+ do {
+ mixinTypeNames.add(name);
name = readIndexedQName();
- }
+ } while (name != null);
+ bundle.setMixinTypeNames(mixinTypeNames);
+ } else {
+ bundle.setMixinTypeNames(Collections.<Name>emptySet());
}
- }
- private void readSharedSet(NodePropBundle bundle) throws IOException {
- Set<NodeId> sharedSet;
- if (version >= BundleBinding.VERSION_3) {
- int n = readVarInt();
- if (n == 0) {
- sharedSet = Collections.emptySet();
- } else if (n == 1) {
- sharedSet = Collections.singleton(readNodeId());
- } else {
- sharedSet = new HashSet<NodeId>();
- for (int i = 0; i < n; i++) {
- sharedSet.add(readNodeId());
- }
+ // properties
+ name = readIndexedQName();
+ while (name != null) {
+ PropertyId pId = new PropertyId(bundle.getId(), name);
+ NodePropBundle.PropertyEntry pState = readPropertyEntry(pId);
+ // skip redundant primaryType, mixinTypes and uuid properties
+ if (!name.equals(NameConstants.JCR_PRIMARYTYPE)
+ && !name.equals(NameConstants.JCR_MIXINTYPES)
+ && !name.equals(NameConstants.JCR_UUID)) {
+ bundle.addProperty(pState);
}
- } else if (version == BundleBinding.VERSION_2) {
+ name = readIndexedQName();
+ }
+
+ // set referenceable flag
+ bundle.setReferenceable(in.readBoolean());
+
+ // child nodes (list of uuid/name pairs)
+ NodeId childId = readNodeId();
+ while (childId != null) {
+ bundle.addChildNodeEntry(readQName(), childId);
+ childId = readNodeId();
+ }
+
+ // read modcount, since version 1.0
+ if (version >= BundleBinding.VERSION_1) {
+ bundle.setModCount(in.readShort());
+ }
+
+ // read shared set, since version 2.0
+ if (version >= BundleBinding.VERSION_2) {
// shared set (list of parent uuids)
NodeId parentId = readNodeId();
if (parentId != null) {
- sharedSet = new HashSet<NodeId>();
+ Set<NodeId> shared = new HashSet<NodeId>();
do {
- sharedSet.add(parentId);
+ shared.add(parentId);
parentId = readNodeId();
} while (parentId != null);
+ bundle.setSharedSet(shared);
} else {
- sharedSet = Collections.emptySet();
- }
- } else {
- sharedSet = Collections.emptySet();
- }
- bundle.setSharedSet(sharedSet);
- }
-
- private void readChildNodeEntries(NodePropBundle bundle) throws IOException {
- if (version >= BundleBinding.VERSION_3) {
- int n = readVarInt();
- for (int i = 0; i < n; i++) {
- NodeId id = readNodeId();
- Name name = readQName();
- bundle.addChildNodeEntry(name, id);
+ bundle.setSharedSet(Collections.<NodeId>emptySet());
}
} else {
- NodeId childId = readNodeId();
- while (childId != null) {
- bundle.addChildNodeEntry(readQName(), childId);
- childId = readNodeId();
- }
+ bundle.setSharedSet(Collections.<NodeId>emptySet());
}
}
@@ -419,12 +414,7 @@ class BundleReader {
if (version >= BundleBinding.VERSION_3 || in.readBoolean()) {
long msb = in.readLong();
long lsb = in.readLong();
- if (msb != NULL_NODE_ID.getMostSignificantBits()
- || lsb != NULL_NODE_ID.getLeastSignificantBits()) {
- return new NodeId(msb, lsb);
- } else {
- return null;
- }
+ return new NodeId(msb, lsb);
} else {
return null;
}
@@ -526,6 +516,14 @@ class BundleReader {
}
}
+ private int readVarInt(int value, int base) throws IOException {
+ if (value < base) {
+ return value;
+ } else {
+ return readVarInt() + base;
+ }
+ }
+
/**
* Deserializes a variable-length long written using bundle
* serialization version 3.
@@ -639,10 +637,7 @@ class BundleReader {
}
private byte[] readBytes(int len, int base) throws IOException {
- if (len == base) {
- len += readVarInt();
- }
- byte[] bytes = new byte[len];
+ byte[] bytes = new byte[readVarInt(len, base)];
in.readFully(bytes);
return bytes;
}
Modified: jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleWriter.java?rev=1022942&r1=1022941&r2=1022942&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleWriter.java (original)
+++ jackrabbit/trunk/jackrabbit-core/src/main/java/org/apache/jackrabbit/core/persistence/util/BundleWriter.java Fri Oct 15 14:30:22 2010
@@ -25,8 +25,6 @@ import java.math.BigDecimal;
import java.util.Calendar;
import java.util.Collection;
import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Set;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
@@ -93,62 +91,62 @@ class BundleWriter {
writeName(bundle.getNodeTypeName());
// parentUUID
- writeNodeId(bundle.getParentId());
-
- // mixin types
- writeMixinTypes(bundle);
-
- // properties
- writeProperties(bundle);
-
- // write uuid flag
- out.writeBoolean(bundle.isReferenceable());
-
- // child nodes (list of uuid/name pairs)
- writeChildNodeEntries(bundle);
+ NodeId parentId = bundle.getParentId();
+ if (parentId == null) {
+ parentId = BundleBinding.NULL_PARENT_ID;
+ }
+ writeNodeId(parentId);
// write mod count
writeVarInt(bundle.getModCount());
- // write shared set
- writeSharedSet(bundle);
+ Collection<Name> mixins = bundle.getMixinTypeNames();
+ Collection<PropertyEntry> properties = bundle.getPropertyEntries();
+ Collection<ChildNodeEntry> nodes = bundle.getChildNodeEntries();
+ Collection<NodeId> shared = bundle.getSharedSet();
- // set size of bundle
- bundle.setSize(out.size() - size);
- }
+ int mn = mixins.size();
+ int pn = properties.size();
+ int nn = nodes.size();
+ int sn = shared.size();
+ int referenceable = 0;
+ if (bundle.isReferenceable()) {
+ referenceable = 1;
+ }
+ out.writeByte(
+ Math.min(mn, 1) << 7
+ | Math.min(pn, 7) << 4
+ | Math.min(nn, 3) << 2
+ | Math.min(sn, 1) << 1
+ | referenceable);
- private void writeMixinTypes(NodePropBundle bundle) throws IOException {
- Set<Name> mixins = bundle.getMixinTypeNames();
- writeVarInt(mixins.size());
+ // mixin types
+ writeVarInt(mn, 1);
for (Name name : mixins) {
writeName(name);
}
- }
- private void writeProperties(NodePropBundle bundle) throws IOException {
- Collection<PropertyEntry> properties = bundle.getPropertyEntries();
- writeVarInt(properties.size());
+ // properties
+ writeVarInt(pn, 7);
for (PropertyEntry property : properties) {
writeState(property);
}
- }
- private void writeChildNodeEntries(NodePropBundle bundle)
- throws IOException {
- List<ChildNodeEntry> chilren = bundle.getChildNodeEntries();
- writeVarInt(chilren.size());
- for (ChildNodeEntry child : chilren) {
- writeNodeId(child.getId()); // uuid
+ // child nodes (list of name/uuid pairs)
+ writeVarInt(nn, 3);
+ for (ChildNodeEntry child : nodes) {
writeName(child.getName()); // name
+ writeNodeId(child.getId()); // uuid
}
- }
- private void writeSharedSet(NodePropBundle bundle) throws IOException {
- Set<NodeId> sharedSet = bundle.getSharedSet();
- writeVarInt(sharedSet.size());
- for (NodeId nodeId: sharedSet) {
+ // write shared set
+ writeVarInt(sn, 1);
+ for (NodeId nodeId: shared) {
writeNodeId(nodeId);
}
+
+ // set size of bundle
+ bundle.setSize(out.size() - size);
}
/**
@@ -381,9 +379,6 @@ class BundleWriter {
* @throws IOException in an I/O error occurs.
*/
private void writeNodeId(NodeId id) throws IOException {
- if (id == null) {
- id = BundleBinding.NULL_NODE_ID;
- }
out.writeLong(id.getMostSignificantBits());
out.writeLong(id.getLeastSignificantBits());
}
@@ -517,6 +512,12 @@ class BundleWriter {
}
}
+ private void writeVarInt(int value, int base) throws IOException {
+ if (value >= base) {
+ writeVarInt(value - base);
+ }
+ }
+
/**
* Serializes a long value using a variable length encoding like the
* one used by {@link #writeVarInt(int)} for integer values. Before