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/02/25 15:50:20 UTC

svn commit: r1449732 - 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: Mon Feb 25 14:50:20 2013
New Revision: 1449732

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

Reduce the number of readSegment() calls by keeping better track of the current segment where referenced values are most likely located

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/SegmentPropertyState.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentReader.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordTest.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=1449732&r1=1449731&r2=1449732&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 Mon Feb 25 14:50:20 2013
@@ -19,10 +19,12 @@ package org.apache.jackrabbit.oak.plugin
 import static com.google.common.base.Preconditions.checkElementIndex;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkPositionIndexes;
+import static org.apache.jackrabbit.oak.plugins.segment.SegmentWriter.BLOCK_SIZE;
 
 import java.nio.ByteBuffer;
 import java.util.UUID;
 
+import com.google.common.base.Charsets;
 import com.google.common.cache.Weigher;
 
 class Segment {
@@ -92,8 +94,27 @@ class Segment {
     private final OffsetCache<String> strings = new OffsetCache<String>() {
         @Override
         protected String load(int offset) {
-            return new SegmentReader(store).readString(
-                    new RecordId(uuid, offset));
+            int pos = offset - (MAX_SEGMENT_SIZE - data.length);
+            checkElementIndex(pos, data.length);
+            long length = internalReadLength(pos);
+            if (length < SMALL_LIMIT) {
+                return new String(data, pos + 1, (int) length, Charsets.UTF_8);
+            } else if (length < MEDIUM_LIMIT) {
+                return new String(data, pos + 2, (int) length, Charsets.UTF_8);
+            } else if (length < Integer.MAX_VALUE) {
+                int size = (int) ((length + BLOCK_SIZE - 1) / BLOCK_SIZE);
+                ListRecord list = new ListRecord(readRecordId(offset + 8), size);
+                SegmentStream stream = new SegmentStream(
+                        new SegmentReader(store), new RecordId(uuid, offset),
+                        list, length);
+                try {
+                    return stream.getString();
+                } finally {
+                    stream.close();
+                }
+            } else {
+                throw new IllegalStateException("String is too long: " + length);
+            }
         }
     };
 
@@ -185,4 +206,31 @@ class Segment {
         return segment.readString(id.getOffset());
     }
 
+    long readLength(int position) {
+        int pos = position - (MAX_SEGMENT_SIZE - data.length);
+        checkElementIndex(pos, data.length);
+        return internalReadLength(pos);
+    }
+
+    private long internalReadLength(int pos) {
+        int length = data[pos++] & 0xff;
+        if ((length & 0x80) == 0) {
+            return length;
+        } else if ((length & 0x40) == 0) {
+            return ((length & 0x3f) << 8
+                    | data[pos++] & 0xff)
+                    + SMALL_LIMIT;
+        } else {
+            return (((long) length & 0x3f) << 56
+                    | ((long) (data[pos++] & 0xff)) << 48
+                    | ((long) (data[pos++] & 0xff)) << 40
+                    | ((long) (data[pos++] & 0xff)) << 32
+                    | ((long) (data[pos++] & 0xff)) << 24
+                    | ((long) (data[pos++] & 0xff)) << 16
+                    | ((long) (data[pos++] & 0xff)) << 8
+                    | ((long) (data[pos++] & 0xff)))
+                    + MEDIUM_LIMIT;
+        }
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java?rev=1449732&r1=1449731&r2=1449732&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentPropertyState.java Mon Feb 25 14:50:20 2013
@@ -113,12 +113,14 @@ class SegmentPropertyState extends Abstr
         checkNotNull(type);
         checkArgument(!type.isArray(), "Type must not be an array type");
 
+        Segment segment = reader.getStore().readSegment(recordId.getSegmentId());
+
         Type<?> base;
         ListRecord values;
         if (isArray()) {
             base = getType().getBaseType();
-            int size = reader.readInt(recordId, 0);
-            RecordId listId = reader.readRecordId(recordId, 4);
+            int size = segment.readInt(recordId.getOffset());
+            RecordId listId = segment.readRecordId(recordId.getOffset() + 4);
             values = new ListRecord(listId, size);
         } else {
             base = getType();
@@ -130,7 +132,7 @@ class SegmentPropertyState extends Abstr
         if (type == Type.BINARY) {
             return (T) new SegmentBlob(reader, valueId);
         } else {
-            String value = reader.readString(valueId);
+            String value = segment.readString(valueId);
             if (type == Type.STRING || type == Type.URI
                     || type == Type.NAME || type == Type.PATH
                     || type == Type.REFERENCE || type == Type.WEAKREFERENCE) {

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentReader.java?rev=1449732&r1=1449731&r2=1449732&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentReader.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentReader.java Mon Feb 25 14:50:20 2013
@@ -37,12 +37,6 @@ public class SegmentReader {
 
     private final SegmentStore store;
 
-    private final LoadingCache<RecordId, String> strings =
-            CacheBuilder.newBuilder()
-            .maximumWeight(1 << 20) // 1 MB
-            .weigher(newStringWeigher())
-            .build(newStringLoader());
-
     private final LoadingCache<RecordId, Template> templates =
             CacheBuilder.newBuilder()
             .maximumSize(1000)
@@ -52,29 +46,6 @@ public class SegmentReader {
         this.store = store;
     }
 
-    private static Weigher<RecordId, String> newStringWeigher() {
-        return new Weigher<RecordId, String>() {
-            @Override
-            public int weigh(RecordId key, String value) {
-                return 32 + value.length() * 2;
-            }
-        };
-    }
-
-    private CacheLoader<RecordId, String> newStringLoader() {
-        return new CacheLoader<RecordId, String>() {
-            @Override
-            public String load(RecordId key) throws Exception {
-                SegmentStream stream = readStream(key);
-                try {
-                    return stream.getString();
-                } finally {
-                    stream.close();
-                }
-            }
-        };
-    }
-
     private CacheLoader<RecordId, Template> newTemplateLoader() {
         return new CacheLoader<RecordId, Template>() {
             @Override
@@ -95,7 +66,7 @@ public class SegmentReader {
                 if (hasPrimaryType) {
                     RecordId primaryId = segment.readRecordId(offset);
                     primaryType = PropertyStates.createProperty(
-                            "jcr:primaryType", readString(primaryId), Type.NAME);
+                            "jcr:primaryType", segment.readString(primaryId), Type.NAME);
                     offset += Segment.RECORD_ID_BYTES;
                 }
 
@@ -104,7 +75,7 @@ public class SegmentReader {
                     String[] mixins = new String[mixinCount];
                     for (int i = 0; i < mixins.length; i++) {
                         RecordId mixinId = segment.readRecordId(offset);
-                        mixins[i] = readString(mixinId);
+                        mixins[i] =  segment.readString(mixinId);
                         offset += Segment.RECORD_ID_BYTES;
                     }
                     mixinTypes = PropertyStates.createProperty(
@@ -116,7 +87,7 @@ public class SegmentReader {
                     childName = Template.MANY_CHILD_NODES;
                 } else if (!zeroChildNodes) {
                     RecordId childNameId = segment.readRecordId(offset);
-                    childName = readString(childNameId);
+                    childName = segment.readString(childNameId);
                     offset += Segment.RECORD_ID_BYTES;
                 }
 
@@ -127,7 +98,7 @@ public class SegmentReader {
                     offset += Segment.RECORD_ID_BYTES;
                     byte type = segment.readByte(offset++);
                     properties[i] = new PropertyTemplate(
-                            readString(propertyNameId),
+                            segment.readString(propertyNameId),
                             Type.fromTag(Math.abs(type), type < 0));
                 }
 
@@ -146,15 +117,6 @@ public class SegmentReader {
         }
     }
 
-    public String readString(RecordId recordId) {
-        try {
-            return strings.get(recordId);
-        } catch (ExecutionException e) {
-            throw new IllegalStateException(
-                    "Unable to access string record " + recordId, e);
-        }
-    }
-
     public long readLength(RecordId recordId) {
         checkNotNull(recordId);
         Segment segment = store.readSegment(recordId.getSegmentId());
@@ -162,24 +124,7 @@ public class SegmentReader {
     }
 
     private long readLength(Segment segment, int offset) {
-        int length = segment.readByte(offset++) & 0xff;
-        if ((length & 0x80) == 0) {
-            return length;
-        } else if ((length & 0x40) == 0) {
-            return ((length & 0x3f) << 8
-                    | segment.readByte(offset) & 0xff)
-                    + Segment.SMALL_LIMIT;
-        } else {
-            return (((long) length & 0x3f) << 56
-                    | ((long) (segment.readByte(offset++) & 0xff)) << 48
-                    | ((long) (segment.readByte(offset++) & 0xff)) << 40
-                    | ((long) (segment.readByte(offset++) & 0xff)) << 32
-                    | ((long) (segment.readByte(offset++) & 0xff)) << 24
-                    | ((long) (segment.readByte(offset++) & 0xff)) << 16
-                    | ((long) (segment.readByte(offset++) & 0xff)) << 8
-                    | ((long) (segment.readByte(offset) & 0xff)))
-                    + Segment.MEDIUM_LIMIT;
-        }
+        return segment.readLength(offset);
     }
 
     public SegmentStream readStream(RecordId recordId) {

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordTest.java?rev=1449732&r1=1449731&r2=1449732&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/segment/RecordTest.java Mon Feb 25 14:50:20 2013
@@ -161,11 +161,12 @@ public class RecordTest {
         RecordId large = writer.writeString(builder.toString());
 
         writer.flush();
+        Segment segment = store.readSegment(large.getSegmentId());
 
-        assertEquals("", reader.readString(empty));
-        assertEquals(" ", reader.readString(space));
-        assertEquals("Hello, World!", reader.readString(hello));
-        assertEquals(builder.toString(), reader.readString(large));
+        assertEquals("", segment.readString(empty));
+        assertEquals(" ", segment.readString(space));
+        assertEquals("Hello, World!", segment.readString(hello));
+        assertEquals(builder.toString(), segment.readString(large));
     }
 
     @Test