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) @@ -218,51 +218,82 @@ } } + private RecordNumbers cachedRecordNumbers; + + private final Object cachedRecordNumbersLock = new Object(); + /** * Read the serialized table mapping record numbers to offsets. * * @return An instance of {@link RecordNumbers}, never {@code null}. */ private RecordNumbers readRecordNumberOffsets() { - Map recordNumberOffsets = newLinkedHashMap(); + if (cachedRecordNumbers != null) { + return cachedRecordNumbers; + } - int position = data.position(); + synchronized (cachedRecordNumbersLock) { + if (cachedRecordNumbers != null) { + return cachedRecordNumbers; + } - position += HEADER_SIZE; - position += getReferencedSegmentIdCount() * SEGMENT_REFERENCE_SIZE; + Map recordNumberOffsets = newLinkedHashMap(); - 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)); + int position = data.position(); + + 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)); + } + + cachedRecordNumbers = new ImmutableRecordNumbers(recordNumberOffsets); } - return new ImmutableRecordNumbers(recordNumberOffsets); + return cachedRecordNumbers; } + private SegmentReferences cachedSegmentReferences; + + private final Object cachedSegmentReferencesLock = new Object(); + private SegmentReferences readReferencedSegments() { - checkState(getReferencedSegmentIdCount() + 1 < 0xffff, - "Segment cannot have more than 0xffff references"); + if (cachedSegmentReferences != null) { + return cachedSegmentReferences; + } - List referencedSegments = newArrayListWithCapacity(getReferencedSegmentIdCount()); + synchronized (cachedSegmentReferencesLock) { + if (cachedSegmentReferences != null) { + return cachedSegmentReferences; + } - int position = data.position(); + checkState(getReferencedSegmentIdCount() + 1 < 0xffff, "Segment cannot have more than 0xffff references"); - position += HEADER_SIZE; + List referencedSegments = newArrayListWithCapacity(getReferencedSegmentIdCount()); - 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)); + int position = data.position(); + + 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)); + } + + cachedSegmentReferences = new ImmutableSegmentReferences(referencedSegments); } - return new ImmutableSegmentReferences(referencedSegments); + return cachedSegmentReferences; } Segment(@Nonnull SegmentStore store,