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());
     }
 
 }


Reply via email to