jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ju...@apache.org
Subject svn commit: r1539759 - in /jackrabbit/oak/trunk/oak-core/src: main/java/org/apache/jackrabbit/oak/plugins/segment/ test/java/org/apache/jackrabbit/oak/plugins/segment/
Date Thu, 07 Nov 2013 18:50:12 GMT
Author: jukka
Date: Thu Nov  7 18:50:12 2013
New Revision: 1539759

URL: http://svn.apache.org/r1539759
Log:
OAK-1152: SegmentMK: Improved debuggability

Include header information in non-bulk segments

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordId.java
    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/RecordId.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordId.java?rev=1539759&r1=1539758&r2=1539759&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordId.java
(original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/RecordId.java
Thu Nov  7 18:50:12 2013
@@ -42,7 +42,7 @@ public final class RecordId implements C
 
     public RecordId(UUID segmentId, int offset) {
         checkArgument(offset < Segment.MAX_SEGMENT_SIZE);
-        checkArgument((offset & (Segment.RECORD_ALIGN_BYTES - 1)) == 0);
+        checkArgument(offset == Segment.align(offset));
         this.segmentId = checkNotNull(segmentId);
         this.offset = offset;
     }

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=1539759&r1=1539758&r2=1539759&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
Thu Nov  7 18:50:12 2013
@@ -54,8 +54,12 @@ public class Segment {
      * The number of bytes (or bits of address space) to use for the
      * alignment boundary of segment records.
      */
-    static final int RECORD_ALIGN_BITS = 2;
-    static final int RECORD_ALIGN_BYTES = 1 << RECORD_ALIGN_BITS; // 4
+    static final int RECORD_ALIGN_BITS = 2; // align at the four-byte boundary
+
+    static int align(int value) {
+        int mask = -1 << RECORD_ALIGN_BITS;
+        return (value + ~mask) & mask;
+    }
 
     /**
      * Maximum segment size. Record identifiers are stored as three-byte
@@ -96,10 +100,22 @@ public class Segment {
 
     private final ByteBuffer data;
 
+    private final int refposition;
+
     public Segment(SegmentStore store, UUID uuid, ByteBuffer data) {
         this.store = checkNotNull(store);
         this.uuid = checkNotNull(uuid);
         this.data = checkNotNull(data);
+
+        if (data.capacity() > 0
+                && data.capacity() < Segment.MAX_SEGMENT_SIZE) {
+            // so skip the header parts of a normal non-bulk, non-empty segment
+            int roots = data.getShort(data.position() + 1) & 0xffff;
+            int headerSize = 3 + roots * 3;
+            this.refposition = data.position() + align(headerSize);
+        } else {
+            this.refposition = data.position();
+        }
     }
 
     /**
@@ -176,7 +192,7 @@ public class Segment {
         UUID refid;
         int refpos = data.get(pos) & 0xff;
         if (refpos != 0xff) {
-            refpos = data.position() + refpos * 16;
+            refpos = refposition + refpos * 16;
             refid = new UUID(data.getLong(refpos), data.getLong(refpos + 8));
         } else {
             refid = uuid;

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=1539759&r1=1539758&r2=1539759&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
Thu Nov  7 18:50:12 2013
@@ -32,6 +32,7 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.api.Type.NAMES;
 import static org.apache.jackrabbit.oak.plugins.segment.MapRecord.BUCKETS_PER_LEVEL;
 import static org.apache.jackrabbit.oak.plugins.segment.Segment.MAX_SEGMENT_SIZE;
+import static org.apache.jackrabbit.oak.plugins.segment.Segment.align;
 
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
@@ -108,7 +109,7 @@ public class SegmentWriter {
      * The set of root records (i.e. ones not referenced by other records)
      * in this segment.
      */
-    private final Map<RecordId, RecordType> roots = newHashMap();
+    private final Map<RecordId, RecordType> roots = newLinkedHashMap();
 
     /**
      * The segment write buffer, filled from the end to the beginning
@@ -138,14 +139,37 @@ public class SegmentWriter {
                 new Segment(store, UUID.randomUUID(), ByteBuffer.allocate(0));
     }
 
+    private void writeSegmentHeader(ByteBuffer b) {
+        int p = b.position();
+
+        b.put((byte) refids.size());
+        b.putShort((short) roots.size());
+
+        for (Map.Entry<RecordId, RecordType> entry : roots.entrySet()) {
+            int offset = entry.getKey().getOffset();
+            b.put((byte) entry.getValue().ordinal());
+            b.put((byte) (offset >> (8 + Segment.RECORD_ALIGN_BITS)));
+            b.put((byte) (offset >> Segment.RECORD_ALIGN_BITS));
+        }
+
+        p = b.position() - p;
+        int q = Segment.align(p);
+        for (int i = p; i < q; i++) {
+            b.put((byte) 0);
+        }
+
+        for (UUID refid : refids.keySet()) {
+            b.putLong(refid.getMostSignificantBits());
+            b.putLong(refid.getLeastSignificantBits());
+        }
+    }
+
     public synchronized Segment getCurrentSegment(UUID id) {
         if (equal(id, uuid)) {
             if (currentSegment == null) {
-                ByteBuffer b = ByteBuffer.allocate(16 * refids.size() + length);
-                for (UUID refid : refids.keySet()) {
-                    b.putLong(refid.getMostSignificantBits());
-                    b.putLong(refid.getLeastSignificantBits());
-                }
+                int header = align(3 + roots.size() * 3) + 16 * refids.size();
+                ByteBuffer b = ByteBuffer.allocate(header + length);
+                writeSegmentHeader(b);
                 b.put(buffer, buffer.length - length, length);
                 b.rewind();
                 currentSegment = new Segment(store, uuid, b);
@@ -162,14 +186,11 @@ public class SegmentWriter {
 
     public synchronized void flush() {
         if (length > 0) {
-            length += 16 * refids.size();
+            length += align(3 + roots.size() * 3) + refids.size() * 16;
 
             ByteBuffer b = ByteBuffer.wrap(
-                    buffer, buffer.length - length, 16 * refids.size());
-            for (UUID refid : refids.keySet()) {
-                b.putLong(refid.getMostSignificantBits());
-                b.putLong(refid.getLeastSignificantBits());
-            }
+                    buffer, buffer.length - length, length);
+            writeSegmentHeader(b);
 
             store.writeSegment(uuid, buffer, buffer.length - length, length);
 
@@ -204,19 +225,16 @@ public class SegmentWriter {
         rootIds.removeAll(ids);
         int rootCount = rootIds.size() + 1;
 
-        int fullSize = size + ids.size() * Segment.RECORD_ID_BYTES;
-        int alignment = Segment.RECORD_ALIGN_BYTES - 1;
-        int alignedSize = (fullSize + alignment) & ~alignment;
-
-        int segmentSize =
-                3 + rootCount * 3 + refCount * 16 + alignedSize + length;
+        int recordSize = Segment.align(size + ids.size() * Segment.RECORD_ID_BYTES);
+        int headerSize = Segment.align(3 + rootCount * 3);
+        int segmentSize = headerSize + refCount * 16 + recordSize + length;
         if (segmentSize > buffer.length - 1
                 || rootCount > 0xffff
                 || refCount > Segment.SEGMENT_REFERENCE_LIMIT) {
             flush();
         }
 
-        length += alignedSize;
+        length += recordSize;
         position = buffer.length - length;
         checkState(position >= 0);
 
@@ -247,7 +265,7 @@ public class SegmentWriter {
 
         int offset = id.getOffset();
         checkState(0 <= offset && offset < MAX_SEGMENT_SIZE);
-        checkState((offset & (Segment.RECORD_ALIGN_BYTES - 1)) == 0);
+        checkState(offset == Segment.align(offset));
 
         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=1539759&r1=1539758&r2=1539759&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
Thu Nov  7 18:50:12 2013
@@ -40,29 +40,29 @@ public class SegmentSizeTest {
     @Test
     public void testNodeSize() {
         NodeBuilder builder = EMPTY_NODE.builder();
-        assertEquals(20, getSize(builder));
+        assertEquals(28, getSize(builder));
         assertEquals(4, getAmortizedSize(builder));
 
         builder = EMPTY_NODE.builder();
         builder.setProperty("foo", "bar");
-        assertEquals(24, getSize(builder));
+        assertEquals(32, getSize(builder));
         assertEquals(8, getAmortizedSize(builder));
 
         builder = EMPTY_NODE.builder();
         builder.setProperty("foo", "bar");
         builder.setProperty("baz", 123);
-        assertEquals(40, getSize(builder));
+        assertEquals(48, getSize(builder));
         assertEquals(12, getAmortizedSize(builder));
 
         builder = EMPTY_NODE.builder();
         builder.child("foo");
-        assertEquals(40, getSize(builder));
+        assertEquals(48, getSize(builder));
         assertEquals(12, getAmortizedSize(builder));
 
         builder = EMPTY_NODE.builder();
         builder.child("foo");
         builder.child("bar");
-        assertEquals(68, getSize(builder));
+        assertEquals(76, 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(20, getSize(builder));
+        assertEquals(28, 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(144, getSize(builder));
+        assertEquals(152, 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(264, getSize(builder));
+        assertEquals(272, 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(356, getSize(builder));
+        assertEquals(364, 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(412, getSize(builder));
+        assertEquals(420, 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(26744, Segment.WEIGHER.weigh(null, segment));
+        assertEquals(26752, 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(128, Segment.WEIGHER.weigh(null, segment));
+        assertEquals(136, Segment.WEIGHER.weigh(null, segment));
     }
 
     private int getSize(NodeBuilder builder) {
@@ -187,7 +187,7 @@ public class SegmentSizeTest {
         writer.writeNode(state);
         id = writer.writeNode(state).getRecordId();
         segment = store.readSegment(id.getSegmentId());
-        return Segment.WEIGHER.weigh(null, segment) - base;
+        return Segment.WEIGHER.weigh(null, segment) - base - 4;
     }
 
 }



Mime
View raw message