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 15:16:34 UTC

svn commit: r1022908 - 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 13:16:34 2010
New Revision: 1022908

URL: http://svn.apache.org/viewvc?rev=1022908&view=rev
Log:
JCR-2762: Optimize bundle serialization

Avoid the extra byte in front of all node identifiers by using variable-length counts before the child node list and the shared set.

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=1022908&r1=1022907&r2=1022908&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 13:16:34 2010
@@ -34,6 +34,15 @@ 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
+     * <code>00000000-0000-0000-0000-000000000000</code>.
+     */
+    static final NodeId NULL_NODE_ID =
+        new NodeId("bb4e9d10-d857-11df-937b-0800200c9a66");
+
+    /**
      * serialization version 1
      */
     static final int VERSION_1 = 1;

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=1022908&r1=1022907&r2=1022908&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 13:16:34 2010
@@ -16,6 +16,8 @@
  */
 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;
@@ -29,6 +31,7 @@ import java.io.DataInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Calendar;
+import java.util.Collections;
 import java.util.GregorianCalendar;
 import java.util.HashSet;
 import java.util.Set;
@@ -174,11 +177,7 @@ class BundleReader {
         bundle.setReferenceable(in.readBoolean());
 
         // child nodes (list of uuid/name pairs)
-        NodeId childId = readNodeId();
-        while (childId != null) {
-            bundle.addChildNodeEntry(readQName(), childId);
-            childId = readNodeId();
-        }
+        readChildNodeEntries(bundle);
 
         // read modcount, since version 1.0
         if (version >= BundleBinding.VERSION_3) {
@@ -188,18 +187,58 @@ class BundleReader {
         }
 
         // read shared set, since version 2.0
-        Set<NodeId> sharedSet = new HashSet<NodeId>();
-        if (version >= BundleBinding.VERSION_2) {
+        readSharedSet(bundle);
+
+        return bundle;
+    }
+
+    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());
+                }
+            }
+        } else if (version == BundleBinding.VERSION_2) {
             // shared set (list of parent uuids)
             NodeId parentId = readNodeId();
-            while (parentId != null) {
-                sharedSet.add(parentId);
-                parentId = readNodeId();
+            if (parentId != null) {
+                sharedSet = new HashSet<NodeId>();
+                do {
+                    sharedSet.add(parentId);
+                    parentId = readNodeId();
+                } while (parentId != null);
+            } else {
+                sharedSet = Collections.emptySet();
             }
+        } else {
+            sharedSet = Collections.emptySet();
         }
         bundle.setSharedSet(sharedSet);
+    }
 
-        return bundle;
+    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);
+            }
+        } else {
+            NodeId childId = readNodeId();
+            while (childId != null) {
+                bundle.addChildNodeEntry(readQName(), childId);
+                childId = readNodeId();
+            }
+        }
     }
 
     /**
@@ -342,10 +381,15 @@ class BundleReader {
      * @throws IOException in an I/O error occurs.
      */
     private NodeId readNodeId() throws IOException {
-        if (in.readBoolean()) {
+        if (version >= BundleBinding.VERSION_3 || in.readBoolean()) {
             long msb = in.readLong();
             long lsb = in.readLong();
-            return new NodeId(msb, lsb);
+            if (msb != NULL_NODE_ID.getMostSignificantBits()
+                    || lsb != NULL_NODE_ID.getLeastSignificantBits()) {
+                return new NodeId(msb, lsb);
+            } else {
+                return null;
+            }
         } else {
             return null;
         }

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=1022908&r1=1022907&r2=1022908&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 13:16:34 2010
@@ -24,6 +24,8 @@ import java.io.OutputStream;
 import java.math.BigDecimal;
 import java.util.Calendar;
 import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Set;
 
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
@@ -32,6 +34,7 @@ import org.apache.commons.io.IOUtils;
 import org.apache.jackrabbit.core.data.DataStore;
 import org.apache.jackrabbit.core.id.NodeId;
 import org.apache.jackrabbit.core.value.InternalValue;
+import org.apache.jackrabbit.core.persistence.util.NodePropBundle.ChildNodeEntry;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.slf4j.Logger;
@@ -119,25 +122,36 @@ class BundleWriter {
         out.writeBoolean(bundle.isReferenceable());
 
         // child nodes (list of uuid/name pairs)
-        for (NodePropBundle.ChildNodeEntry entry : bundle.getChildNodeEntries()) {
-            writeNodeId(entry.getId());  // uuid
-            writeName(entry.getName());   // name
-        }
-        writeNodeId(null);
+        writeChildNodeEntries(bundle);
 
         // write mod count
         writeVarInt(bundle.getModCount());
 
         // write shared set
-        for (NodeId nodeId: bundle.getSharedSet()) {
-            writeNodeId(nodeId);
-        }
-        writeNodeId(null);
+        writeSharedSet(bundle);
 
         // set size of bundle
         bundle.setSize(out.size() - size);
     }
 
+    private void writeChildNodeEntries(NodePropBundle bundle)
+            throws IOException {
+        List<ChildNodeEntry> chilren = bundle.getChildNodeEntries();
+        writeVarInt(chilren.size());
+        for (ChildNodeEntry child : chilren) {
+            writeNodeId(child.getId());   // uuid
+            writeName(child.getName());   // name
+        }
+    }
+
+    private void writeSharedSet(NodePropBundle bundle) throws IOException {
+        Set<NodeId> sharedSet = bundle.getSharedSet();
+        writeVarInt(sharedSet.size());
+        for (NodeId nodeId: sharedSet) {
+            writeNodeId(nodeId);
+        }
+    }
+
     /**
      * Serializes a property entry. The serialization begins with a single
      * byte that encodes the type and multi-valuedness of the property:
@@ -366,12 +380,10 @@ class BundleWriter {
      */
     private void writeNodeId(NodeId id) throws IOException {
         if (id == null) {
-            out.writeBoolean(false);
-        } else {
-            out.writeBoolean(true);
-            out.writeLong(id.getMostSignificantBits());
-            out.writeLong(id.getLeastSignificantBits());
+            id = BundleBinding.NULL_NODE_ID;
         }
+        out.writeLong(id.getMostSignificantBits());
+        out.writeLong(id.getLeastSignificantBits());
     }
 
     /**