Index: oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java (date 1474536154000) +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java (date 1474495426000) @@ -22,7 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkPositionIndexes; import static com.google.common.base.Preconditions.checkState; -import static com.google.common.collect.Maps.newHashMap; import static org.apache.jackrabbit.oak.commons.IOUtils.closeQuietly; import static org.apache.jackrabbit.oak.segment.SegmentId.isDataSegmentId; import static org.apache.jackrabbit.oak.segment.SegmentVersion.LATEST_VERSION; @@ -37,7 +36,6 @@ import java.nio.channels.Channels; import java.nio.channels.WritableByteChannel; import java.util.Arrays; -import java.util.Map; import java.util.UUID; import javax.annotation.CheckForNull; @@ -67,7 +65,7 @@ * 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,8 +138,6 @@ @Nonnull private final SegmentVersion version; - private final Map recordIdCache = newHashMap(); - /** * Unpacks a 4 byte aligned segment offset. * @param offset 4 byte aligned segment offset @@ -386,28 +382,19 @@ } private RecordId internalReadRecordId(int pos) { - RecordId recordId = recordIdCache.get(pos); - - if (recordId != null) { - return recordId; + int refIndex = data.getInt(pos); + SegmentId refId; + if (refIndex == 0) { + refId = getSegmentId(); + } else { + int position = data.position() + HEADER_SIZE + (refIndex - 1) * 16; + long msb = data.getLong(position); + long lsb = data.getLong(position + 8); + refId = store.newSegmentId(msb, lsb); } - synchronized (recordIdCache) { - recordId = recordIdCache.get(pos); - - if (recordId != null) { - return recordId; - } - - 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); - - recordIdCache.put(pos, recordId); - - return recordId; - } + int offset = (data.getShort(pos + 4) & 0xffff) << RECORD_ALIGN_BITS; + return new RecordId(refId, offset); } @Nonnull Index: oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java (date 1474536154000) +++ oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/standby/MBeanTest.java (date 1474495426000) @@ -195,7 +195,7 @@ 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); Index: oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== --- oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java (date 1474536154000) +++ oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java (date 1474495426000) @@ -23,6 +23,7 @@ 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 @@ */ private final Map roots = newLinkedHashMap(); - private final Set referencedSegmentIds = newHashSet(); + private final Map referencedSegmentIds = newHashMap(); @Nonnull private final SegmentStore store; @@ -285,17 +286,26 @@ checkState(0 <= offset && offset < MAX_SEGMENT_SIZE); checkState(offset == align(offset, 1 << Segment.RECORD_ALIGN_BITS)); - SegmentId segmentId = recordId.getSegmentId(); - checkGCGeneration(segmentId); + SegmentId refId = recordId.getSegmentId(); + checkGCGeneration(refId); - writeLong(segmentId.getMostSignificantBits()); - writeLong(segmentId.getLeastSignificantBits()); + Integer refIndex; + if (refId.equals(segment.getSegmentId())) { + refIndex = 0; + } else { + refIndex = referencedSegmentIds.get(refId); + if (refIndex == null) { + refIndex = referencedSegmentIds.size() + 1; + referencedSegmentIds.put(refId, refIndex); + + BinaryUtils.writeInt(buffer, Segment.REFERENCED_SEGMENT_ID_COUNT_OFFSET, refIndex); + BinaryUtils.writeLong(buffer, HEADER_SIZE + refIndex * 16 - 16, refId.getMostSignificantBits()); + BinaryUtils.writeLong(buffer, HEADER_SIZE + refIndex * 16 - 8, refId.getLeastSignificantBits()); + } + } + writeInt(refIndex); writeShort((short)((offset >> Segment.RECORD_ALIGN_BITS) & 0xffff)); - if (!segmentId.equals(segment.getSegmentId())) { - referencedSegmentIds.add(segmentId); - } - statistics.recordIdCount++; dirty = true; @@ -350,7 +360,6 @@ 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 +370,7 @@ 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 +386,6 @@ length = buffer.length; } - for (SegmentId id : referencedSegmentIds) { - pos = BinaryUtils.writeLong(buffer, pos, id.getMostSignificantBits()); - pos = BinaryUtils.writeLong(buffer, pos, id.getLeastSignificantBits()); - } - for (Map.Entry 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 +459,7 @@ // Adjust the estimation of the new referenced segment ID count. for (SegmentId segmentId : segmentIds) { - if (referencedSegmentIds.contains(segmentId.asUUID())) { + if (referencedSegmentIds.containsKey(segmentId)) { referencedIdCount--; } }