Author: frm
Date: Tue Sep 27 09:46:25 2016
New Revision: 1762431

URL: http://svn.apache.org/viewvc?rev=1762431&view=rev
Log:
OAK-4844 - Introduce a segment ID reference table in every segment

Modified:
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java?rev=1762431&r1=1762430&r2=1762431&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
 Tue Sep 27 09:46:25 2016
@@ -67,7 +67,7 @@ public class Segment {
      * is used for identifying the segment and two for the record offset
      * within that segment.
      */
-    static final int RECORD_ID_BYTES = 8 + 8 + 2;
+    static final int RECORD_ID_BYTES = 4 + 2;
 
     /**
      * The limit on segment references within one segment. Since record
@@ -140,7 +140,7 @@ public class Segment {
     @Nonnull
     private final SegmentVersion version;
 
-    private final Map<Integer, RecordId> recordIdCache = newHashMap();
+    private final Map<Integer, SegmentId> segmentIdCache = newHashMap();
 
     /**
      * Unpacks a 4 byte aligned segment offset.
@@ -386,27 +386,39 @@ public class Segment {
     }
 
     private RecordId internalReadRecordId(int pos) {
-        RecordId recordId = recordIdCache.get(pos);
+        SegmentId segmentId = dereferenceSegmentId(data.getInt(pos));
+        int offset = (data.getShort(pos + 4) & 0xffff) << RECORD_ALIGN_BITS;
+        return new RecordId(segmentId, offset);
+    }
+
+    private SegmentId dereferenceSegmentId(int reference) {
+        if (reference == 0) {
+            return id;
+        }
 
-        if (recordId != null) {
-            return recordId;
+        SegmentId id = segmentIdCache.get(reference);
+
+        if (id != null) {
+            return id;
         }
 
-        synchronized (recordIdCache) {
-            recordId = recordIdCache.get(pos);
+        synchronized (segmentIdCache) {
+            id = segmentIdCache.get(reference);
 
-            if (recordId != null) {
-                return recordId;
+            if (id != null) {
+                return id;
             }
 
-            long msb = data.getLong(pos);
-            long lsb = data.getLong(pos + 8);
-            int offset = (data.getShort(pos + 16) & 0xffff) << 
RECORD_ALIGN_BITS;
-            recordId = new RecordId(store.newSegmentId(msb, lsb), offset);
+            int position = data.position() + HEADER_SIZE + (reference - 1) * 
16;
+
+            long msb = data.getLong(position);
+            long lsb = data.getLong(position + 8);
+
+            id = store.newSegmentId(msb, lsb);
 
-            recordIdCache.put(pos, recordId);
+            segmentIdCache.put(reference, id);
 
-            return recordId;
+            return id;
         }
     }
 

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java?rev=1762431&r1=1762430&r2=1762431&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
 Tue Sep 27 09:46:25 2016
@@ -23,6 +23,7 @@ import static com.google.common.base.Cha
 import static com.google.common.base.Preconditions.checkArgument;
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.Maps.newHashMap;
 import static com.google.common.collect.Maps.newLinkedHashMap;
 import static com.google.common.collect.Sets.newHashSet;
 import static java.lang.System.arraycopy;
@@ -112,7 +113,7 @@ public class SegmentBufferWriter impleme
      */
     private final Map<RecordId, RecordType> roots = newLinkedHashMap();
 
-    private final Set<SegmentId> referencedSegmentIds = newHashSet();
+    private final Map<SegmentId, Integer> referencedSegmentIds = newHashMap();
 
     @Nonnull
     private final SegmentStore store;
@@ -286,21 +287,38 @@ public class SegmentBufferWriter impleme
         checkState(offset == align(offset, 1 << Segment.RECORD_ALIGN_BITS));
 
         SegmentId segmentId = recordId.getSegmentId();
-        checkGCGeneration(segmentId);
 
-        writeLong(segmentId.getMostSignificantBits());
-        writeLong(segmentId.getLeastSignificantBits());
-        writeShort((short)((offset >> Segment.RECORD_ALIGN_BITS) & 0xffff));
+        checkGCGeneration(segmentId);
 
-        if (!segmentId.equals(segment.getSegmentId())) {
-            referencedSegmentIds.add(segmentId);
-        }
+        writeInt(writeSegmentIdReference(segmentId));
+        writeShort((short) ((offset >> Segment.RECORD_ALIGN_BITS) & 0xffff));
 
         statistics.recordIdCount++;
 
         dirty = true;
     }
 
+    private int writeSegmentIdReference(SegmentId id) {
+        if (id.equals(segment.getSegmentId())) {
+            return 0;
+        }
+
+        Integer reference = referencedSegmentIds.get(id);
+
+        if (reference != null) {
+            return reference;
+        }
+
+        reference = referencedSegmentIds.size() + 1;
+        referencedSegmentIds.put(id, reference);
+
+        BinaryUtils.writeInt(buffer, 
Segment.REFERENCED_SEGMENT_ID_COUNT_OFFSET, reference);
+        BinaryUtils.writeLong(buffer, HEADER_SIZE + reference * 16 - 16, 
id.getMostSignificantBits());
+        BinaryUtils.writeLong(buffer, HEADER_SIZE + reference * 16 - 8, 
id.getLeastSignificantBits());
+
+        return reference;
+    }
+
     /**
      * Check that the generation of a segment matches the generation of this 
writer and logs
      * a warning otherwise.
@@ -350,7 +368,6 @@ public class SegmentBufferWriter impleme
             BinaryUtils.writeShort(buffer, Segment.ROOT_COUNT_OFFSET, (short) 
rootcount);
 
             int referencedSegmentIdCount = referencedSegmentIds.size();
-            BinaryUtils.writeInt(buffer, 
Segment.REFERENCED_SEGMENT_ID_COUNT_OFFSET, referencedSegmentIdCount);
             statistics.segmentIdCount = referencedSegmentIdCount;
 
             int totalLength = align(HEADER_SIZE + referencedSegmentIdCount * 
16 + rootcount * 3 + length, 16);
@@ -361,7 +378,7 @@ public class SegmentBufferWriter impleme
 
             statistics.size = length = totalLength;
 
-            int pos = HEADER_SIZE;
+            int pos = HEADER_SIZE + referencedSegmentIdCount * 16;
             if (pos + length <= buffer.length) {
                 // the whole segment fits to the space *after* the referenced
                 // segment identifiers we've already written, so we can safely
@@ -377,11 +394,6 @@ public class SegmentBufferWriter impleme
                 length = buffer.length;
             }
 
-            for (SegmentId id : referencedSegmentIds) {
-                pos = BinaryUtils.writeLong(buffer, pos, 
id.getMostSignificantBits());
-                pos = BinaryUtils.writeLong(buffer, pos, 
id.getLeastSignificantBits());
-            }
-
             for (Map.Entry<RecordId, RecordType> entry : roots.entrySet()) {
                 pos = BinaryUtils.writeByte(buffer, pos, (byte) 
entry.getValue().ordinal());
                 pos = BinaryUtils.writeShort(buffer, pos, (short) 
(entry.getKey().getOffset() >> Segment.RECORD_ALIGN_BITS));
@@ -455,7 +467,7 @@ public class SegmentBufferWriter impleme
             // Adjust the estimation of the new referenced segment ID count.
 
             for (SegmentId segmentId : segmentIds) {
-                if (referencedSegmentIds.contains(segmentId.asUUID())) {
+                if (referencedSegmentIds.containsKey(segmentId)) {
                     referencedIdCount--;
                 }
             }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java?rev=1762431&r1=1762430&r2=1762431&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java
 Tue Sep 27 09:46:25 2016
@@ -195,7 +195,7 @@ public class MBeanTest extends TestBase
             assertEquals("1", jmxServer.invoke(clientStatus, 
"calcSecondsSinceLastSuccess", null, null).toString());
 
             assertEquals(new Long(1), jmxServer.getAttribute(connectionStatus, 
"TransferredSegments"));
-            assertEquals(new Long(208), 
jmxServer.getAttribute(connectionStatus, "TransferredSegmentBytes"));
+            assertEquals(new Long(128), 
jmxServer.getAttribute(connectionStatus, "TransferredSegmentBytes"));
             
             // stop the master
             jmxServer.invoke(serverStatus, "stop", null, null);


Reply via email to