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);