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/07 14:13:25 UTC

svn commit: r1443449 - 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: Thu Feb  7 13:13:25 2013
New Revision: 1443449

URL: http://svn.apache.org/viewvc?rev=1443449&view=rev
Log:
OAK-593: Segment-based MK

Refactor the Record classes to take the SegmentReader as
an argument instead of keeping an internal reference to it.
This makes them more lightweight and allows RecordId to
be merged into Record and thus SegmentWriter to return full
Record instances instead of just RecordIds.

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/BlockRecord.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentReader.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.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/BlockRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/BlockRecord.java?rev=1443449&r1=1443448&r2=1443449&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/BlockRecord.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/BlockRecord.java Thu Feb  7 13:13:25 2013
@@ -24,8 +24,8 @@ class BlockRecord extends Record {
 
     private final int size;
 
-    BlockRecord(SegmentReader reader, RecordId id, int size) {
-        super(reader, id);
+    BlockRecord(RecordId id, int size) {
+        super(id);
         this.size = size;
     }
 
@@ -34,13 +34,16 @@ class BlockRecord extends Record {
      * read starting from the given position within this block. The number
      * of bytes read is returned.
      *
+     * @param reader segment reader
      * @param position position within this block
      * @param buffer target buffer
      * @param offset offset within the target buffer
      * @param length maximum number of bytes to read
      * @return number of bytes that could be read
      */
-    public int read(int position, byte[] buffer, int offset, int length) {
+    public int read(
+            SegmentReader reader, int position,
+            byte[] buffer, int offset, int length) {
         checkElementIndex(position, size);
         checkNotNull(buffer);
         checkPositionIndexes(offset, offset + length, buffer.length);
@@ -49,8 +52,7 @@ class BlockRecord extends Record {
             length = size - position;
         }
         if (length > 0) {
-            getReader().readBytes(
-                    getRecordId(), position, buffer, offset, length);
+            reader.readBytes(getRecordId(), position, buffer, offset, length);
         }
         return length;
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java?rev=1443449&r1=1443448&r2=1443449&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/ListRecord.java Thu Feb  7 13:13:25 2013
@@ -27,8 +27,8 @@ class ListRecord extends Record {
 
     private final int bucketSize;
 
-    ListRecord(SegmentReader reader, RecordId id, int size) {
-        super(reader, id);
+    ListRecord(RecordId id, int size) {
+        super(id);
         checkArgument(size >= 0);
         this.size = size;
 
@@ -43,7 +43,7 @@ class ListRecord extends Record {
         return size;
     }
 
-    public RecordId getEntry(int index) {
+    public RecordId getEntry(SegmentReader reader, int index) {
         checkElementIndex(index, size);
 
         if (size == 1) {
@@ -51,10 +51,10 @@ class ListRecord extends Record {
         } else {
             int bucketIndex = index / bucketSize;
             int bucketOffset = index % bucketSize;
-            RecordId bucketId = readRecordId(bucketIndex * 4);
+            RecordId bucketId = readRecordId(reader, bucketIndex * 4);
             ListRecord bucket =
-                new ListRecord(getReader(), bucketId, bucketSize);
-            return bucket.getEntry(bucketOffset);
+                new ListRecord(bucketId, bucketSize);
+            return bucket.getEntry(reader, bucketOffset);
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java?rev=1443449&r1=1443448&r2=1443449&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/MapRecord.java Thu Feb  7 13:13:25 2013
@@ -22,49 +22,49 @@ class MapRecord extends Record {
 
     static final int LEVEL_BITS = 6;
 
-    MapRecord(SegmentReader reader, RecordId id) {
-        super(reader, id);
+    MapRecord(RecordId id) {
+        super(id);
     }
 
-    public int size() {
-        return readInt(0);
+    public int size(SegmentReader reader) {
+        return readInt(reader, 0);
     }
 
-    public RecordId getEntry(String key) {
+    public RecordId getEntry(SegmentReader reader, String key) {
         checkNotNull(key);
-        return getEntry(key, 0);
+        return getEntry(reader, key, 0);
     }
 
-    private RecordId getEntry(String key, int level) {
+    private RecordId getEntry(SegmentReader reader, String key, int level) {
         int size = 1 << LEVEL_BITS;
         int mask = size - 1;
         int shift = level * LEVEL_BITS;
 
         int code = key.hashCode();
-        int bucketSize = readInt(0);
+        int bucketSize = readInt(reader, 0);
         if (bucketSize == 0) {
             return null;
-        } else if (bucketSize <= size) {
+        } else if (bucketSize <= size || shift >= 32) {
             int offset = 0;
-            while (offset < bucketSize && readInt(4 + offset * 4) < code) {
+            while (offset < bucketSize && readInt(reader, 4 + offset * 4) < code) {
                 offset++;
             }
-            while (offset < bucketSize && readInt(4 + offset * 4) == code) {
-                RecordId keyId = readRecordId(4 + (bucketSize + offset) * 4);
-                if (key.equals(getReader().readString(keyId))) {
-                    return readRecordId(4 + (2 * bucketSize + offset) * 4);
+            while (offset < bucketSize && readInt(reader, 4 + offset * 4) == code) {
+                RecordId keyId = readRecordId(reader, 4 + (bucketSize + offset) * 4);
+                if (key.equals(reader.readString(keyId))) {
+                    return readRecordId(reader, 4 + (2 * bucketSize + offset) * 4);
                 }
                 offset++;
             }
             return null;
         } else {
-            long bucketMap = readLong(4);
+            long bucketMap = readLong(reader, 4);
             int bucketIndex = (code >> shift) & mask;
             long bucketBit = 1L << bucketIndex;
             if ((bucketMap & bucketBit) != 0) {
                 bucketIndex = Long.bitCount(bucketMap & (bucketBit - 1));
-                RecordId bucketId = readRecordId(12 + bucketIndex * 4);
-                return new MapRecord(getReader(), bucketId).getEntry(key, level + 1);
+                RecordId bucketId = readRecordId(reader, 12 + bucketIndex * 4);
+                return new MapRecord(bucketId).getEntry(reader, key, level + 1);
             } else {
                 return null;
             }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java?rev=1443449&r1=1443448&r2=1443449&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/Record.java Thu Feb  7 13:13:25 2013
@@ -18,28 +18,21 @@ package org.apache.jackrabbit.oak.plugin
 
 class Record {
 
-    private final SegmentReader reader;
-
     private final RecordId id;
 
-    protected Record(SegmentReader reader, RecordId id) {
-        this.reader = reader;
+    protected Record(RecordId id) {
         this.id = id;
     }
 
-    protected SegmentReader getReader() {
-        return reader;
-    }
-
-    protected RecordId readRecordId(int position) {
+    protected RecordId readRecordId(SegmentReader reader, int position) {
         return reader.readRecordId(id, position);
     }
 
-    protected int readInt(int position) {
+    protected int readInt(SegmentReader reader, int position) {
         return reader.readInt(id, position);
     }
 
-    protected long readLong(int position) {
+    protected long readLong(SegmentReader reader, int position) {
         return reader.readLong(id, position);
     }
 

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=1443449&r1=1443448&r2=1443449&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 Thu Feb  7 13:13:25 2013
@@ -56,8 +56,8 @@ public class SegmentReader {
         int offset = recordId.getOffset();
         long length = segment.readLong(offset);
         int size = (int) ((length + BLOCK_SIZE - 1) / BLOCK_SIZE);
-        ListRecord list = new ListRecord(
-                this, segment.readRecordId(offset + 8), size);
+        ListRecord list =
+            new ListRecord(segment.readRecordId(offset + 8), size);
         return new SegmentStream(this, list, length);
     }
 
@@ -103,16 +103,16 @@ public class SegmentReader {
         if (numberOfEntries > 0) {
             Segment segment = store.readSegment(recordId.getSegmentId());
             RecordId id = segment.readRecordId(recordId.getOffset());
-            return new ListRecord(this, id, numberOfEntries);
+            return new ListRecord(id, numberOfEntries);
         } else {
-            return new ListRecord(this, recordId, numberOfEntries);
+            return new ListRecord(recordId, numberOfEntries);
         }
     }
 
     public BlockRecord readBlock(RecordId recordId, int size) {
         checkNotNull(recordId);
         checkArgument(size > 0);
-        return new BlockRecord(this, recordId, size);
+        return new BlockRecord(recordId, size);
     }
 
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java?rev=1443449&r1=1443448&r2=1443449&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/SegmentStream.java Thu Feb  7 13:13:25 2013
@@ -89,9 +89,9 @@ public class SegmentStream extends Input
                 len = (int) (length - position);
             }
 
-            BlockRecord block =
-                reader.readBlock(blocks.getEntry(blockIndex), BLOCK_SIZE);
-            len = block.read(blockOffset, b, off, len);
+            BlockRecord block = reader.readBlock(
+                    blocks.getEntry(reader, blockIndex), BLOCK_SIZE);
+            len = block.read(reader, blockOffset, b, off, len);
             position += len;
             return len;
         }

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=1443449&r1=1443448&r2=1443449&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 Thu Feb  7 13:13:25 2013
@@ -53,20 +53,20 @@ public class RecordTest {
     public void testBlockRecord() {
         RecordId blockId = writer.writeBlock(bytes, 0, bytes.length);
         writer.flush();
-        BlockRecord block = new BlockRecord(reader, blockId, bytes.length);
+        BlockRecord block = new BlockRecord(blockId, bytes.length);
 
         // Check reading with all valid positions and lengths
         for (int n = 1; n < bytes.length; n++) {
             for (int i = 0; i + n <= bytes.length; i++) {
                 Arrays.fill(bytes, i, i + n, (byte) '.');
-                assertEquals(n, block.read(i, bytes, i, n));
+                assertEquals(n, block.read(reader, i, bytes, i, n));
                 assertEquals(hello, new String(bytes, Charsets.UTF_8));
             }
         }
 
         // Check reading with a too long length
         byte[] large = new byte[bytes.length * 2];
-        assertEquals(bytes.length, block.read(0, large, 0, large.length));
+        assertEquals(bytes.length, block.read(reader, 0, large, 0, large.length));
         assertEquals(hello, new String(large, 0, bytes.length, Charsets.UTF_8));
     }
 
@@ -84,24 +84,24 @@ public class RecordTest {
 
         assertEquals(0, zero.size());
         assertEquals(1, one.size());
-        assertEquals(blockId, one.getEntry(0));
+        assertEquals(blockId, one.getEntry(reader, 0));
         assertEquals(LEVEL_SIZE, level1.size());
-        assertEquals(blockId, level1.getEntry(0));
-        assertEquals(blockId, level1.getEntry(LEVEL_SIZE - 1));
+        assertEquals(blockId, level1.getEntry(reader, 0));
+        assertEquals(blockId, level1.getEntry(reader, LEVEL_SIZE - 1));
         assertEquals(LEVEL_SIZE + 1, level1p.size());
-        assertEquals(blockId, level1p.getEntry(0));
-        assertEquals(blockId, level1p.getEntry(LEVEL_SIZE));
+        assertEquals(blockId, level1p.getEntry(reader, 0));
+        assertEquals(blockId, level1p.getEntry(reader, LEVEL_SIZE));
         assertEquals(LEVEL_SIZE * LEVEL_SIZE, level2.size());
-        assertEquals(blockId, level2.getEntry(0));
-        assertEquals(blockId, level2.getEntry(LEVEL_SIZE * LEVEL_SIZE - 1));
+        assertEquals(blockId, level2.getEntry(reader, 0));
+        assertEquals(blockId, level2.getEntry(reader, LEVEL_SIZE * LEVEL_SIZE - 1));
         assertEquals(LEVEL_SIZE * LEVEL_SIZE + 1, level2p.size());
-        assertEquals(blockId, level2p.getEntry(0));
-        assertEquals(blockId, level2p.getEntry(LEVEL_SIZE * LEVEL_SIZE));
+        assertEquals(blockId, level2p.getEntry(reader, 0));
+        assertEquals(blockId, level2p.getEntry(reader, LEVEL_SIZE * LEVEL_SIZE));
     }
 
     private ListRecord writeList(int size, RecordId id) {
         List<RecordId> list = Collections.nCopies(size, id);
-        return new ListRecord(reader, writer.writeList(list), size);
+        return new ListRecord(writer.writeList(list), size);
     }
 
     @Test
@@ -166,34 +166,34 @@ public class RecordTest {
     public void testMapRecord() {
         RecordId blockId = writer.writeBlock(bytes, 0, bytes.length);
 
-        MapRecord zero = new MapRecord(reader, writer.writeMap(
+        MapRecord zero = new MapRecord(writer.writeMap(
                 ImmutableMap.<String, RecordId>of()));
-        MapRecord one = new MapRecord(reader, writer.writeMap(
+        MapRecord one = new MapRecord(writer.writeMap(
                 ImmutableMap.of("one", blockId)));
-        MapRecord two = new MapRecord(reader, writer.writeMap(
+        MapRecord two = new MapRecord(writer.writeMap(
                 ImmutableMap.of("one", blockId, "two", blockId)));
         Map<String, RecordId> map = Maps.newHashMap();
         for (int i = 0; i < 1000; i++) {
             map.put("key" + i, blockId);
         }
-         MapRecord many = new MapRecord(reader, writer.writeMap(map));
+        MapRecord many = new MapRecord(writer.writeMap(map));
 
         writer.flush();
 
-        assertEquals(0, zero.size());
-        assertNull(zero.getEntry("one"));
-        assertEquals(1, one.size());
-        assertEquals(blockId, one.getEntry("one"));
-        assertNull(one.getEntry("two"));
-        assertEquals(2, two.size());
-        assertEquals(blockId, two.getEntry("one"));
-        assertEquals(blockId, two.getEntry("two"));
-        assertNull(two.getEntry("three"));
-        assertEquals(1000, many.size());
+        assertEquals(0, zero.size(reader));
+        assertNull(zero.getEntry(reader, "one"));
+        assertEquals(1, one.size(reader));
+        assertEquals(blockId, one.getEntry(reader, "one"));
+        assertNull(one.getEntry(reader, "two"));
+        assertEquals(2, two.size(reader));
+        assertEquals(blockId, two.getEntry(reader, "one"));
+        assertEquals(blockId, two.getEntry(reader, "two"));
+        assertNull(two.getEntry(reader, "three"));
+        assertEquals(1000, many.size(reader));
         for (int i = 0; i < 1000; i++) {
-            assertEquals(blockId, many.getEntry("key" + i));
+            assertEquals(blockId, many.getEntry(reader, "key" + i));
         }
-        assertNull(many.getEntry("foo"));
+        assertNull(many.getEntry(reader, "foo"));
     }
 
 }