Author: frm Date: Tue Apr 24 12:26:00 2018 New Revision: 1829986 URL: http://svn.apache.org/viewvc?rev=1829986&view=rev Log: OAK-7440 - Split estimation implementations into separate components
SizeDeltaGcEstimation contains an implementation of the estimation phase that is overloaded with logic pertaining to both the full and tail compaction. This commit defines EstiamtionStrategy, replacing GCEstimation, and splits SizeDeltaGcEstimation in two implementations. The two implementations both satisfy the EstimationStrategy interface. Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationResult.java - copied, changed from r1829985, jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCEstimationResult.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationStrategy.java (with props) jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FullSizeDeltaEstimationStrategy.java (with props) jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TailSizeDeltaEstimationStrategy.java (with props) Removed: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCEstimation.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCEstimationResult.java Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/DefaultGarbageCollectionStrategy.java jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/DefaultGarbageCollectionStrategy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/DefaultGarbageCollectionStrategy.java?rev=1829986&r1=1829985&r2=1829986&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/DefaultGarbageCollectionStrategy.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/DefaultGarbageCollectionStrategy.java Tue Apr 24 12:26:00 2018 @@ -31,7 +31,6 @@ import org.apache.jackrabbit.oak.segment import org.apache.jackrabbit.oak.segment.SegmentReader; import org.apache.jackrabbit.oak.segment.SegmentTracker; import org.apache.jackrabbit.oak.segment.compaction.SegmentGCOptions; -import org.apache.jackrabbit.oak.segment.file.CleanupStrategy.Context; import org.apache.jackrabbit.oak.segment.file.tar.GCGeneration; import org.apache.jackrabbit.oak.segment.file.tar.TarFiles; import org.apache.jackrabbit.oak.spi.blob.BlobStore; @@ -99,7 +98,7 @@ class DefaultGarbageCollectionStrategy i context.getGCListener().updateStatus(ESTIMATION.message()); PrintableStopwatch watch = PrintableStopwatch.createStarted(); - GCEstimationResult estimation = estimateCompactionGain(context, full); + EstimationResult estimation = estimateCompactionGain(context, full); sufficientEstimatedGain = estimation.isGcNeeded(); String gcLog = estimation.getGcLog(); if (sufficientEstimatedGain) { @@ -218,7 +217,7 @@ class DefaultGarbageCollectionStrategy i return tailCompactionStrategy.compact(newCompactionStrategyContext(context)); } - private GCEstimationResult estimateCompactionGain(Context context, boolean full) { + private EstimationResult estimateCompactionGain(Context context, boolean full) { return new SizeDeltaGcEstimation( context.getGCOptions().getGcSizeDeltaEstimation(), context.getGCJournal(), Copied: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationResult.java (from r1829985, jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCEstimationResult.java) URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationResult.java?p2=jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationResult.java&p1=jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCEstimationResult.java&r1=1829985&r2=1829986&rev=1829986&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCEstimationResult.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationResult.java Tue Apr 24 12:26:00 2018 @@ -17,13 +17,13 @@ package org.apache.jackrabbit.oak.segment.file; -class GCEstimationResult { +class EstimationResult { private final boolean gcNeeded; private final String gcLog; - GCEstimationResult(boolean gcNeeded, String gcLog) { + EstimationResult(boolean gcNeeded, String gcLog) { this.gcNeeded = gcNeeded; this.gcLog = gcLog; } Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationStrategy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationStrategy.java?rev=1829986&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationStrategy.java (added) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationStrategy.java Tue Apr 24 12:26:00 2018 @@ -0,0 +1,36 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.jackrabbit.oak.segment.file; + +interface EstimationStrategy { + + interface Context { + + long getSizeDelta(); + + long getCurrentSize(); + + GCJournal getGCJournal(); + + } + + EstimationResult estimate(Context context); + +} Propchange: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/EstimationStrategy.java ------------------------------------------------------------------------------ svn:eol-style = native Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FullSizeDeltaEstimationStrategy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FullSizeDeltaEstimationStrategy.java?rev=1829986&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FullSizeDeltaEstimationStrategy.java (added) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FullSizeDeltaEstimationStrategy.java Tue Apr 24 12:26:00 2018 @@ -0,0 +1,109 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.jackrabbit.oak.segment.file; + +import static com.google.common.collect.Lists.newArrayList; +import static java.lang.String.format; +import static org.apache.jackrabbit.oak.segment.file.PrintableBytes.newPrintableBytes; + +import java.util.ArrayList; +import java.util.List; + +import org.apache.jackrabbit.oak.segment.file.GCJournal.GCJournalEntry; + +class FullSizeDeltaEstimationStrategy implements EstimationStrategy { + + @Override + public EstimationResult estimate(Context context) { + if (context.getSizeDelta() == 0) { + return new EstimationResult(true, "Estimation skipped because the size delta value equals 0"); + } + + long previousSize = readPreviousSize(context); + + if (previousSize < 0) { + return new EstimationResult(true, "Estimation skipped because of missing gc journal data (expected on first run)"); + } + + if (previousIsTail(context)) { + return new EstimationResult(true, "Detected previous garbage collection of type tail so running full garbage collection now."); + } + + long gain = context.getCurrentSize() - previousSize; + boolean gcNeeded = gain > context.getSizeDelta(); + String gcInfo = format( + "Segmentstore size has increased since the last full garbage collection from %s to %s, an increase of %s or %s%%. ", + newPrintableBytes(previousSize), + newPrintableBytes(context.getCurrentSize()), + newPrintableBytes(gain), + 100 * gain / previousSize + ); + if (gcNeeded) { + gcInfo = gcInfo + format( + "This is greater than sizeDeltaEstimation=%s, so running garbage collection", + newPrintableBytes(context.getSizeDelta()) + ); + } else { + gcInfo = gcInfo + format( + "This is less than sizeDeltaEstimation=%s, so skipping garbage collection", + newPrintableBytes(context.getSizeDelta()) + ); + } + return new EstimationResult(gcNeeded, gcInfo); + } + + private long readPreviousSize(Context context) { + List<GCJournalEntry> entries = new ArrayList<>(context.getGCJournal().readAll()); + + if (entries.isEmpty()) { + return -1; + } + + entries.sort((a, b) -> { + if (a.getGcGeneration().getFullGeneration() > b.getGcGeneration().getFullGeneration()) { + return -1; + } + if (a.getGcGeneration().getFullGeneration() < b.getGcGeneration().getFullGeneration()) { + return 1; + } + return Integer.compare(a.getGcGeneration().getGeneration(), b.getGcGeneration().getGeneration()); + }); + + return entries.iterator().next().getRepoSize(); + } + + private boolean previousIsTail(Context context) { + List<GCJournalEntry> entries = newArrayList(context.getGCJournal().readAll()); + if (entries.isEmpty()) { + // We should not get here but if we do the condition is vacuously true + return true; + } else if (entries.size() == 1) { + // A single entry in the gc log must be from a full compaction + // as an initial compaction cannot be of type tail + return false; + } else { + int m = entries.get(entries.size() - 2).getGcGeneration().getFullGeneration(); + int n = entries.get(entries.size() - 1).getGcGeneration().getFullGeneration(); + // No change in the full generation indicates the last compaction was of type tail + return m == n; + } + } + +} Propchange: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FullSizeDeltaEstimationStrategy.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java?rev=1829986&r1=1829985&r2=1829986&view=diff ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java (original) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java Tue Apr 24 12:26:00 2018 @@ -19,122 +19,45 @@ package org.apache.jackrabbit.oak.segment.file; -import static com.google.common.base.Preconditions.checkNotNull; -import static com.google.common.collect.Lists.newArrayList; -import static java.lang.String.format; -import static org.apache.jackrabbit.oak.segment.file.PrintableBytes.newPrintableBytes; - -import java.util.ArrayList; -import java.util.List; - import javax.annotation.Nonnull; -import org.apache.jackrabbit.oak.segment.file.GCJournal.GCJournalEntry; - -class SizeDeltaGcEstimation implements GCEstimation { - - private final long delta; +import org.apache.jackrabbit.oak.segment.file.EstimationStrategy.Context; - private final GCJournal gcJournal; +class SizeDeltaGcEstimation { - private final long currentSize; + private final EstimationStrategy estimationStrategy; - private final boolean full; + private final EstimationStrategy.Context context; SizeDeltaGcEstimation(long delta, @Nonnull GCJournal gcJournal, long currentSize, boolean full) { - this.delta = delta; - this.gcJournal = checkNotNull(gcJournal); - this.currentSize = currentSize; - this.full = full; - } - - @Override - public GCEstimationResult estimate() { - if (delta == 0) { - return new GCEstimationResult(true, "Estimation skipped because the size delta value equals 0"); - } - - long previousSize = readPreviousSize(); - - if (previousSize < 0) { - return new GCEstimationResult(true, "Estimation skipped because of missing gc journal data (expected on first run)"); - } - - if (full && previousIsTail()) { - return new GCEstimationResult(true, - "Detected previous garbage collection of type tail so running full garbage collection now."); - } - - long gain = currentSize - previousSize; - boolean gcNeeded = gain > delta; - String gcInfo = format( - "Segmentstore size has increased since the last %s garbage collection from %s to %s, an increase of %s or %s%%. ", - full ? "full" : "tail", - newPrintableBytes(previousSize), - newPrintableBytes(currentSize), - newPrintableBytes(gain), - 100 * gain / previousSize - ); - if (gcNeeded) { - gcInfo = gcInfo + format( - "This is greater than sizeDeltaEstimation=%s, so running garbage collection", - newPrintableBytes(delta) - ); - } else { - gcInfo = gcInfo + format( - "This is less than sizeDeltaEstimation=%s, so skipping garbage collection", - newPrintableBytes(delta) - ); - } - return new GCEstimationResult(gcNeeded, gcInfo); - } - - private long readPreviousSize() { if (full) { - return readPreviousFullCleanupSize(); + estimationStrategy = new FullSizeDeltaEstimationStrategy(); + } else { + estimationStrategy = new TailSizeDeltaEstimationStrategy(); } - return readPreviousTailCleanupSize(); - } - private long readPreviousFullCleanupSize() { - List<GCJournalEntry> entries = new ArrayList<>(gcJournal.readAll()); + context = new Context() { - if (entries.isEmpty()) { - return -1; - } - - entries.sort((a, b) -> { - if (a.getGcGeneration().getFullGeneration() > b.getGcGeneration().getFullGeneration()) { - return -1; + @Override + public long getSizeDelta() { + return delta; } - if (a.getGcGeneration().getFullGeneration() < b.getGcGeneration().getFullGeneration()) { - return 1; + + @Override + public long getCurrentSize() { + return currentSize; } - return Integer.compare(a.getGcGeneration().getGeneration(), b.getGcGeneration().getGeneration()); - }); - return entries.iterator().next().getRepoSize(); - } + @Override + public GCJournal getGCJournal() { + return gcJournal; + } - private long readPreviousTailCleanupSize() { - return gcJournal.read().getRepoSize(); + }; } - private boolean previousIsTail() { - List<GCJournalEntry> entries = newArrayList(gcJournal.readAll()); - if (entries.isEmpty()) { - // We should not get here but if we do the condition is vacuously true - return true; - } else if (entries.size() == 1) { - // A single entry in the gc log must be from a full compaction - // as an initial compaction cannot be of type tail - return false; - } else { - int m = entries.get(entries.size() - 2).getGcGeneration().getFullGeneration(); - int n = entries.get(entries.size() - 1).getGcGeneration().getFullGeneration(); - // No change in the full generation indicates the last compaction was of type tail - return m == n; - } + public EstimationResult estimate() { + return estimationStrategy.estimate(context); } } Added: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TailSizeDeltaEstimationStrategy.java URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TailSizeDeltaEstimationStrategy.java?rev=1829986&view=auto ============================================================================== --- jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TailSizeDeltaEstimationStrategy.java (added) +++ jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TailSizeDeltaEstimationStrategy.java Tue Apr 24 12:26:00 2018 @@ -0,0 +1,66 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.jackrabbit.oak.segment.file; + +import static java.lang.String.format; +import static org.apache.jackrabbit.oak.segment.file.PrintableBytes.newPrintableBytes; + +class TailSizeDeltaEstimationStrategy implements EstimationStrategy { + + @Override + public EstimationResult estimate(Context context) { + if (context.getSizeDelta() == 0) { + return new EstimationResult(true, "Estimation skipped because the size delta value equals 0"); + } + + long previousSize = readPreviousSize(context); + + if (previousSize < 0) { + return new EstimationResult(true, "Estimation skipped because of missing gc journal data (expected on first run)"); + } + + long gain = context.getCurrentSize() - previousSize; + boolean gcNeeded = gain > context.getSizeDelta(); + String gcInfo = format( + "Segmentstore size has increased since the last tail garbage collection from %s to %s, an increase of %s or %s%%. ", + newPrintableBytes(previousSize), + newPrintableBytes(context.getCurrentSize()), + newPrintableBytes(gain), + 100 * gain / previousSize + ); + if (gcNeeded) { + gcInfo = gcInfo + format( + "This is greater than sizeDeltaEstimation=%s, so running garbage collection", + newPrintableBytes(context.getSizeDelta()) + ); + } else { + gcInfo = gcInfo + format( + "This is less than sizeDeltaEstimation=%s, so skipping garbage collection", + newPrintableBytes(context.getSizeDelta()) + ); + } + return new EstimationResult(gcNeeded, gcInfo); + } + + private long readPreviousSize(Context context) { + return context.getGCJournal().read().getRepoSize(); + } + +} Propchange: jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/TailSizeDeltaEstimationStrategy.java ------------------------------------------------------------------------------ svn:eol-style = native