Author: mduerig
Date: Thu Nov 30 15:44:48 2017
New Revision: 1816720
URL: http://svn.apache.org/viewvc?rev=1816720&view=rev
Log:
OAK-7008: Estimation for FULL can be off sometimes
Unconditionally run full compaction if the previous compaction was a tail
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGcEstimation.java
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGCEstimationTest.java
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=1816720&r1=1816719&r2=1816720&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
Thu Nov 30 15:44:48 2017
@@ -20,6 +20,7 @@
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.commons.IOUtils.humanReadableByteCount;
@@ -59,6 +60,11 @@ class SizeDeltaGcEstimation implements G
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(
@@ -113,4 +119,21 @@ class SizeDeltaGcEstimation implements G
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;
+ }
+ }
+
}
Modified:
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGCEstimationTest.java
URL:
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGCEstimationTest.java?rev=1816720&r1=1816719&r2=1816720&view=diff
==============================================================================
---
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGCEstimationTest.java
(original)
+++
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/SizeDeltaGCEstimationTest.java
Thu Nov 30 15:44:48 2017
@@ -77,25 +77,48 @@ public class SizeDeltaGCEstimationTest {
}
@Test
- public void testFullGCNeeded() throws Exception {
+ public void testFullGCNeededBecauseOfSize1() throws Exception {
journal.persist(100, 1000, newGCGeneration(1, 1, true), 1000, "id");
- journal.persist(110, 1100, newGCGeneration(2, 1, true), 1000, "id");
- journal.persist(120, 1200, newGCGeneration(3, 1, true), 1000, "id");
- journal.persist(130, 1000, newGCGeneration(4, 2, true), 1000, "id");
- journal.persist(100, 1010, newGCGeneration(5, 2, true), 1000, "id");
- journal.persist(110, 1020, newGCGeneration(6, 2, true), 1000, "id");
+ journal.persist(110, 1100, newGCGeneration(2, 2, true), 1000, "id");
+ journal.persist(120, 1200, newGCGeneration(3, 3, true), 1000, "id");
+ journal.persist(130, 1000, newGCGeneration(4, 4, true), 1000, "id");
+ journal.persist(100, 1010, newGCGeneration(5, 5, true), 1000, "id");
+ journal.persist(110, 1020, newGCGeneration(6, 6, true), 1000, "id");
assertTrue(new SizeDeltaGcEstimation(100, journal, 1300,
true).estimate().isGcNeeded());
}
@Test
- public void testFullGCSkipped() throws Exception {
+ public void testFullGCNeededBecauseOfSize2() throws Exception {
+ journal.persist(100, 1000, newGCGeneration(1, 1, true), 1000, "id");
+ assertTrue(new SizeDeltaGcEstimation(10, journal, 1030,
true).estimate().isGcNeeded());
+ }
+
+ @Test
+ public void testFullGCSkippedBecauseOfSize1() throws Exception {
+ journal.persist(100, 1000, newGCGeneration(1, 1, true), 1000, "id");
+ journal.persist(110, 1100, newGCGeneration(2, 2, true), 1000, "id");
+ journal.persist(120, 1200, newGCGeneration(3, 3, true), 1000, "id");
+ journal.persist(130, 1000, newGCGeneration(4, 4, true), 1000, "id");
+ journal.persist(100, 1010, newGCGeneration(5, 5, true), 1000, "id");
+ journal.persist(110, 1020, newGCGeneration(6, 6, true), 1000, "id");
+ assertFalse(new SizeDeltaGcEstimation(100, journal, 1030,
true).estimate().isGcNeeded());
+ }
+
+ @Test
+ public void testFullGCSkippedBecauseOfSize2() throws Exception {
+ journal.persist(100, 1000, newGCGeneration(1, 1, true), 1000, "id");
+ assertFalse(new SizeDeltaGcEstimation(100, journal, 1030,
true).estimate().isGcNeeded());
+ }
+
+ @Test
+ public void testFullGCNeededBecauseOfPreviousTail() throws Exception {
journal.persist(100, 1000, newGCGeneration(1, 1, true), 1000, "id");
journal.persist(110, 1100, newGCGeneration(2, 1, true), 1000, "id");
journal.persist(120, 1200, newGCGeneration(3, 1, true), 1000, "id");
journal.persist(130, 1000, newGCGeneration(4, 2, true), 1000, "id");
journal.persist(100, 1010, newGCGeneration(5, 2, true), 1000, "id");
journal.persist(110, 1020, newGCGeneration(6, 2, true), 1000, "id");
- assertFalse(new SizeDeltaGcEstimation(100, journal, 1030,
true).estimate().isGcNeeded());
+ assertTrue(new SizeDeltaGcEstimation(100, journal, 1030,
true).estimate().isGcNeeded());
}
}