Index: src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java =================================================================== --- src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java (revision 1753237) +++ src/main/java/org/apache/jackrabbit/oak/segment/SegmentWriter.java (working copy) @@ -987,26 +987,11 @@ } assert compactionStats != null; compactionStats.nodeCount++; - if (state instanceof SegmentNodeState) { - SegmentNodeState sns = ((SegmentNodeState) state); - if (sameStore(sns)) { - // This is a segment node state from an old generation. Check whether - // an equivalent one of the current generation is in the cache - if (isOldGeneration(sns.getRecordId())) { - RecordId cachedId = nodeCache.get(sns.getStableId()); - if (cachedId != null) { - compactionStats.cacheHits++; - return cachedId; - } else { - compactionStats.cacheMiss++; - } - } else { - // This segment node state is already in this store, - // no need to write it again, - compactionStats.deDupNodes++; - return sns.getRecordId(); - } - } + + RecordId compactedId = getCompactedRecordId(state); + + if (compactedId != null) { + return compactedId; } compactionStats.writesOps++; @@ -1022,23 +1007,26 @@ } private RecordId writeNodeUncached(@Nonnull NodeState state, int depth) throws IOException { - SegmentNodeState before = null; - Template beforeTemplate = null; ModifiedNodeState after = null; + if (state instanceof ModifiedNodeState) { after = (ModifiedNodeState) state; - NodeState base = after.getBaseState(); - if (base instanceof SegmentNodeState) { - SegmentNodeState sns = ((SegmentNodeState) base); - if (sameStore(sns)) { - if (!isOldGeneration(sns.getRecordId())) { - before = sns; - beforeTemplate = before.getTemplate(); - } - } - } } + RecordId beforeId = null; + + if (after != null) { + beforeId = getCompactedRecordId(after.getBaseState()); + } + + SegmentNodeState before = null; + Template beforeTemplate = null; + + if (beforeId != null) { + before = reader.readNode(beforeId); + beforeTemplate = before.getTemplate(); + } + List ids = newArrayList(); Template template = new Template(reader, state); if (template.equals(beforeTemplate)) { @@ -1116,6 +1104,33 @@ return newNodeStateWriter(stableId, ids).write(writer); } + private RecordId getCompactedRecordId(NodeState n) { + if (!(n instanceof SegmentNodeState)) { + return null; + } + + SegmentNodeState state = (SegmentNodeState) n; + + if (!sameStore(state)) { + return null; + } + + if (!isOldGeneration(state.getRecordId())) { + compactionStats.deDupNodes++; + return state.getRecordId(); + } + + RecordId compacted = nodeCache.get(state.getStableId()); + + if (compacted == null) { + compactionStats.cacheMiss++; + return null; + } + + compactionStats.cacheHits++; + return compacted; + } + /** * @param node * @return {@code true} iff {@code node} originates from the same segment store. Index: src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java =================================================================== --- src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java (revision 1753244) +++ src/test/java/org/apache/jackrabbit/oak/segment/NodeRecordTest.java (working copy) @@ -28,7 +28,6 @@ import org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState; import org.apache.jackrabbit.oak.segment.file.FileStore; import org.apache.jackrabbit.oak.segment.file.FileStoreBuilder; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; @@ -90,7 +89,6 @@ } @Test - @Ignore("OAK-4570") public void baseNodeStateShouldBeReusedAcrossGenerations() throws Exception { try (FileStore store = newFileStore()) { Generation generation = new Generation();