You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2013/10/25 18:39:13 UTC

svn commit: r1535775 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/segment/ test/java/org/apache/jackrabbit/oak/plugins/segment/

Author: jukka
Date: Fri Oct 25 16:39:12 2013
New Revision: 1535775

URL: http://svn.apache.org/r1535775
Log:
OAK-593: Segment-based MK

Special case references to the same segment, to reduce the overhead of
storing and accessing the majority of record identifiers.

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentSizeTest.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java?rev=1535775&r1=1535774&r2=1535775&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Segment.java Fri Oct 25 16:39:12 2013
@@ -47,9 +47,9 @@ public class Segment {
     /**
      * The limit on segment references within one segment. Since record
      * identifiers use one byte to indicate the referenced segment, a single
-     * segment can hold references to up to 256 segments.
+     * segment can hold references to up to 255 segments plus itself.
      */
-    static final int SEGMENT_REFERENCE_LIMIT = 1 << 8; // 256
+    static final int SEGMENT_REFERENCE_LIMIT = (1 << 8) - 1; // 255
 
     /**
      * The number of bytes (or bits of address space) to use for the
@@ -193,8 +193,14 @@ public class Segment {
     }
 
     private RecordId internalReadRecordId(int pos) {
-        int refpos = data.position() + (data.get(pos) & 0xff) * 16;
-        UUID refid = new UUID(data.getLong(refpos), data.getLong(refpos + 8));
+        UUID refid;
+        int refpos = data.get(pos) & 0xff;
+        if (refpos != 0xff) {
+            refpos = data.position() + refpos * 16;
+            refid = new UUID(data.getLong(refpos), data.getLong(refpos + 8));
+        } else {
+            refid = uuid;
+        }
 
         int offset =
                 (((data.get(pos + 1) & 0xff) << 8) | (data.get(pos + 2) & 0xff))

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java?rev=1535775&r1=1535774&r2=1535775&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentWriter.java Fri Oct 25 16:39:12 2013
@@ -161,7 +161,7 @@ public class SegmentWriter {
         Set<UUID> segmentIds = new HashSet<UUID>();
         for (RecordId id : checkNotNull(ids)) {
             UUID segmentId = id.getSegmentId();
-            if (!uuids.containsKey(segmentId)) {
+            if (!equal(uuid, segmentId) && !uuids.containsKey(segmentId)) {
                 segmentIds.add(segmentId);
             }
         }
@@ -187,18 +187,22 @@ public class SegmentWriter {
         checkNotNull(id);
 
         UUID segmentId = id.getSegmentId();
-        Byte segmentIndex = uuids.get(segmentId);
-        if (segmentIndex == null) {
-            checkState(uuids.size() < Segment.SEGMENT_REFERENCE_LIMIT);
-            segmentIndex = Byte.valueOf((byte) uuids.size());
-            uuids.put(segmentId, segmentIndex);
+        if (equal(uuid, segmentId)) {
+            buffer[position++] = (byte) 0xff;
+        } else {
+            Byte segmentIndex = uuids.get(segmentId);
+            if (segmentIndex == null) {
+                checkState(uuids.size() < Segment.SEGMENT_REFERENCE_LIMIT);
+                segmentIndex = Byte.valueOf((byte) uuids.size());
+                uuids.put(segmentId, segmentIndex);
+            }
+            buffer[position++] = segmentIndex.byteValue();
         }
 
         int offset = id.getOffset();
         checkState(0 <= offset && offset < MAX_SEGMENT_SIZE);
         checkState((offset & (Segment.RECORD_ALIGN_BYTES - 1)) == 0);
 
-        buffer[position++] = segmentIndex.byteValue();
         buffer[position++] = (byte) (offset >> (8 + Segment.RECORD_ALIGN_BITS));
         buffer[position++] = (byte) (offset >> Segment.RECORD_ALIGN_BITS);
     }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentSizeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentSizeTest.java?rev=1535775&r1=1535774&r2=1535775&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentSizeTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentSizeTest.java Fri Oct 25 16:39:12 2013
@@ -45,24 +45,24 @@ public class SegmentSizeTest {
 
         builder = EMPTY_NODE.builder();
         builder.setProperty("foo", "bar");
-        assertEquals(40, getSize(builder));
+        assertEquals(24, getSize(builder));
         assertEquals(8, getAmortizedSize(builder));
 
         builder = EMPTY_NODE.builder();
         builder.setProperty("foo", "bar");
         builder.setProperty("baz", 123);
-        assertEquals(56, getSize(builder));
+        assertEquals(40, getSize(builder));
         assertEquals(12, getAmortizedSize(builder));
 
         builder = EMPTY_NODE.builder();
         builder.child("foo");
-        assertEquals(56, getSize(builder));
+        assertEquals(40, getSize(builder));
         assertEquals(12, getAmortizedSize(builder));
 
         builder = EMPTY_NODE.builder();
         builder.child("foo");
         builder.child("bar");
-        assertEquals(84, getSize(builder));
+        assertEquals(68, getSize(builder));
         assertEquals(40, getAmortizedSize(builder));
     }
 
@@ -106,7 +106,7 @@ public class SegmentSizeTest {
     public void testAccessControlNodes() {
         NodeBuilder builder = EMPTY_NODE.builder();
         builder.setProperty("jcr:primaryType", "rep:ACL", Type.NAME);
-        assertEquals(36, getSize(builder));
+        assertEquals(20, getSize(builder));
         assertEquals(4, getAmortizedSize(builder));
 
         NodeBuilder deny = builder.child("deny");
@@ -114,7 +114,7 @@ public class SegmentSizeTest {
         deny.setProperty("rep:principalName", "everyone");
         deny.setProperty(PropertyStates.createProperty(
                 "rep:privileges", ImmutableList.of("jcr:read"), Type.NAMES));
-        assertEquals(160, getSize(builder));
+        assertEquals(144, getSize(builder));
         assertEquals(28, getAmortizedSize(builder));
 
         NodeBuilder allow = builder.child("allow");
@@ -122,7 +122,7 @@ public class SegmentSizeTest {
         allow.setProperty("rep:principalName", "administrators");
         allow.setProperty(PropertyStates.createProperty(
                 "rep:privileges", ImmutableList.of("jcr:all"), Type.NAMES));
-        assertEquals(280, getSize(builder));
+        assertEquals(264, getSize(builder));
         assertEquals(72, getAmortizedSize(builder));
 
         NodeBuilder deny0 = builder.child("deny0");
@@ -131,7 +131,7 @@ public class SegmentSizeTest {
         deny0.setProperty("rep:glob", "*/activities/*");
         builder.setProperty(PropertyStates.createProperty(
                 "rep:privileges", ImmutableList.of("jcr:read"), Type.NAMES));
-        assertEquals(372, getSize(builder));
+        assertEquals(356, getSize(builder));
         assertEquals(108, getAmortizedSize(builder));
 
         NodeBuilder allow0 = builder.child("allow0");
@@ -139,7 +139,7 @@ public class SegmentSizeTest {
         allow0.setProperty("rep:principalName", "user-administrators");
         allow0.setProperty(PropertyStates.createProperty(
                 "rep:privileges", ImmutableList.of("jcr:all"), Type.NAMES));
-        assertEquals(428, getSize(builder));
+        assertEquals(412, getSize(builder));
         assertEquals(136, getAmortizedSize(builder));
     }
 
@@ -155,7 +155,7 @@ public class SegmentSizeTest {
 
         SegmentNodeState state = writer.writeNode(builder.getNodeState());
         Segment segment = store.readSegment(state.getRecordId().getSegmentId());
-        assertEquals(26760, Segment.WEIGHER.weigh(null, segment));
+        assertEquals(26744, Segment.WEIGHER.weigh(null, segment));
 
         writer.flush(); // force flushing of the previous segment
 
@@ -163,7 +163,7 @@ public class SegmentSizeTest {
         builder.child("child1000");
         state = writer.writeNode(builder.getNodeState());
         segment = store.readSegment(state.getRecordId().getSegmentId());
-        assertEquals(144, Segment.WEIGHER.weigh(null, segment));
+        assertEquals(128, Segment.WEIGHER.weigh(null, segment));
     }
 
     private int getSize(NodeBuilder builder) {