Index: src/main/java/org/apache/jackrabbit/oak/segment/Segment.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/segment/Segment.java (revision 1764212) +++ src/main/java/org/apache/jackrabbit/oak/segment/Segment.java (working copy) @@ -40,11 +40,16 @@ import java.util.List; import java.util.Map; import java.util.UUID; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import com.google.common.base.Charsets; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; import org.apache.commons.io.HexDump; import org.apache.commons.io.output.ByteArrayOutputStream; import org.apache.jackrabbit.oak.api.PropertyState; @@ -218,51 +223,80 @@ } } + private static final Cache previousRecordNumbers = CacheBuilder.newBuilder() + .expireAfterAccess(30, TimeUnit.SECONDS) + .build(); + /** * Read the serialized table mapping record numbers to offsets. * * @return An instance of {@link RecordNumbers}, never {@code null}. */ private RecordNumbers readRecordNumberOffsets() { - Map recordNumberOffsets = newLinkedHashMap(); + try { + return previousRecordNumbers.get(getSegmentId().asUUID(), new Callable() { - int position = data.position(); + @Override + public ImmutableRecordNumbers call() throws Exception { + Map recordNumberOffsets = newLinkedHashMap(); - position += HEADER_SIZE; - position += getReferencedSegmentIdCount() * SEGMENT_REFERENCE_SIZE; + int position = data.position(); - for (int i = 0; i < getRecordNumberCount(); i++) { - int recordNumber = data.getInt(position); - position += 4; - int type = data.get(position); - position += 1; - int offset = data.getInt(position); - position += 4; - recordNumberOffsets.put(recordNumber, new RecordEntry(RecordType.values()[type], offset)); + position += HEADER_SIZE; + position += getReferencedSegmentIdCount() * SEGMENT_REFERENCE_SIZE; + + for (int i = 0; i < getRecordNumberCount(); i++) { + int recordNumber = data.getInt(position); + position += 4; + int type = data.get(position); + position += 1; + int offset = data.getInt(position); + position += 4; + recordNumberOffsets.put(recordNumber, new RecordEntry(RecordType.values()[type], offset)); + } + + return new ImmutableRecordNumbers(recordNumberOffsets); + } + + }); + } catch (ExecutionException e) { + throw new RuntimeException(e.getCause()); } - - return new ImmutableRecordNumbers(recordNumberOffsets); } + private static final Cache previousReferencedSegments = CacheBuilder.newBuilder() + .expireAfterAccess(30, TimeUnit.SECONDS) + .build(); + private SegmentReferences readReferencedSegments() { - checkState(getReferencedSegmentIdCount() + 1 < 0xffff, - "Segment cannot have more than 0xffff references"); + try { + return previousReferencedSegments.get(getSegmentId().asUUID(), new Callable() { - List referencedSegments = newArrayListWithCapacity(getReferencedSegmentIdCount()); + @Override + public ImmutableSegmentReferences call() throws Exception { + checkState(getReferencedSegmentIdCount() + 1 < 0xffff, "Segment cannot have more than 0xffff references"); - int position = data.position(); + List referencedSegments = newArrayListWithCapacity(getReferencedSegmentIdCount()); - position += HEADER_SIZE; + int position = data.position(); - for (int i = 0; i < getReferencedSegmentIdCount(); i++) { - long msb = data.getLong(position); - position += 8; - long lsb = data.getLong(position); - position += 8; - referencedSegments.add(store.newSegmentId(msb, lsb)); + position += HEADER_SIZE; + + for (int i = 0; i < getReferencedSegmentIdCount(); i++) { + long msb = data.getLong(position); + position += 8; + long lsb = data.getLong(position); + position += 8; + referencedSegments.add(store.newSegmentId(msb, lsb)); + } + + return new ImmutableSegmentReferences(referencedSegments); + } + + }); + } catch (ExecutionException e) { + throw new RuntimeException(e.getCause()); } - - return new ImmutableSegmentReferences(referencedSegments); } Segment(@Nonnull SegmentStore store,