Author: alexparvulescu
Date: Wed Nov 23 15:57:52 2016
New Revision: 1770994

URL: http://svn.apache.org/viewvc?rev=1770994&view=rev
Log:
OAK-5116 GCJournal should persist size only when compaction is successful


Modified:
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java?rev=1770994&r1=1770993&r2=1770994&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
 Wed Nov 23 15:57:52 2016
@@ -1117,7 +1117,7 @@ public class FileStore extends AbstractF
             long finalSize = size();
             long reclaimedSize = initialSize - afterCleanupSize;
             stats.reclaimed(reclaimedSize);
-            gcJournal.persist(reclaimedSize, finalSize);
+            gcJournal.persist(reclaimedSize, finalSize, getGcGeneration());
             gcListener.cleaned(reclaimedSize, finalSize);
             gcListener.info("TarMK GC #{}: cleanup completed in {} ({} ms). 
Post cleanup size is {} ({} bytes)" +
                             " and space reclaimed {} ({} bytes).",

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java?rev=1770994&r1=1770993&r2=1770994&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/GCJournal.java
 Wed Nov 23 15:57:52 2016
@@ -41,8 +41,9 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 /**
- * Persists the repository size and the reclaimed size following a cleanup 
operation in the
- * {@link #GC_JOURNAL gc journal} file with the format: 'repoSize, 
reclaimedSize, timestamp'.
+ * Persists the repository size and the reclaimed size following a cleanup
+ * operation in the {@link #GC_JOURNAL gc journal} file with the format:
+ * 'repoSize, reclaimedSize, timestamp, gcGen'.
  */
 public class GCJournal {
 
@@ -59,8 +60,20 @@ public class GCJournal {
         this.directory = checkNotNull(directory);
     }
 
-    public synchronized void persist(long reclaimedSize, long repoSize) {
-        latest = new GCJournalEntry(repoSize, reclaimedSize, 
System.currentTimeMillis());
+    /**
+     * Persists the repository size and the reclaimed size following a cleanup
+     * operation
+     */
+    public synchronized void persist(long reclaimedSize, long repoSize,
+            int gcGeneration) {
+        GCJournalEntry current = read();
+        if (current.getGcGeneration() == gcGeneration) {
+            // failed compaction, only update the journal if the generation
+            // increases
+            return;
+        }
+        latest = new GCJournalEntry(repoSize, reclaimedSize,
+                System.currentTimeMillis(), gcGeneration);
         Path path = new File(directory, GC_JOURNAL).toPath();
         try {
             try (BufferedWriter w = newBufferedWriter(path, UTF_8, WRITE,
@@ -73,6 +86,9 @@ public class GCJournal {
         }
     }
 
+    /**
+     * Returns the latest entry available
+     */
     public synchronized GCJournalEntry read() {
         if (latest == null) {
             List<String> all = readLines();
@@ -86,6 +102,9 @@ public class GCJournal {
         return latest;
     }
 
+    /**
+     * Returns all available entries from the journal
+     */
     public synchronized Collection<GCJournalEntry> readAll() {
         List<GCJournalEntry> all = new ArrayList<GCJournalEntry>();
         for (String l : readLines()) {
@@ -108,30 +127,38 @@ public class GCJournal {
 
     static class GCJournalEntry {
 
-        static GCJournalEntry EMPTY = new GCJournalEntry(-1, -1, -1);
+        static GCJournalEntry EMPTY = new GCJournalEntry(-1, -1, -1, -1);
 
         private final long repoSize;
         private final long reclaimedSize;
         private final long ts;
+        private final int gcGeneration;
 
-        public GCJournalEntry(long repoSize, long reclaimedSize, long ts) {
+        public GCJournalEntry(long repoSize, long reclaimedSize, long ts,
+                int gcGeneration) {
             this.repoSize = repoSize;
             this.reclaimedSize = reclaimedSize;
             this.ts = ts;
+            this.gcGeneration = gcGeneration;
         }
 
         @Override
         public String toString() {
-            return  repoSize + "," + reclaimedSize + "," + ts;
+            return repoSize + "," + reclaimedSize + "," + ts + ","
+                    + gcGeneration;
         }
 
         static GCJournalEntry fromString(String in) {
             String[] items = in.split(",");
-            if (items.length == 3) {
+            if (items.length == 3 || items.length == 4) {
                 long repoSize = safeParse(items[0]);
                 long reclaimedSize = safeParse(items[1]);
                 long ts = safeParse(items[2]);
-                return new GCJournalEntry(repoSize, reclaimedSize, ts);
+                int gcGen = -1;
+                if (items.length == 4) {
+                    gcGen = (int) safeParse(items[3]);
+                }
+                return new GCJournalEntry(repoSize, reclaimedSize, ts, gcGen);
             }
             return GCJournalEntry.EMPTY;
         }
@@ -157,11 +184,17 @@ public class GCJournal {
             return ts;
         }
 
+        public int getGcGeneration() {
+            return gcGeneration;
+        }
+
         @Override
         public int hashCode() {
             final int prime = 31;
             int result = 1;
-            result = prime * result + (int) (reclaimedSize ^ (reclaimedSize 
>>> 32));
+            result = prime * result + gcGeneration;
+            result = prime * result
+                    + (int) (reclaimedSize ^ (reclaimedSize >>> 32));
             result = prime * result + (int) (repoSize ^ (repoSize >>> 32));
             result = prime * result + (int) (ts ^ (ts >>> 32));
             return result;
@@ -176,6 +209,8 @@ public class GCJournal {
             if (getClass() != obj.getClass())
                 return false;
             GCJournalEntry other = (GCJournalEntry) obj;
+            if (gcGeneration != other.gcGeneration)
+                return false;
             if (reclaimedSize != other.reclaimedSize)
                 return false;
             if (repoSize != other.repoSize)
@@ -184,5 +219,6 @@ public class GCJournal {
                 return false;
             return true;
         }
+
     }
 }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java?rev=1770994&r1=1770993&r2=1770994&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/GcJournalTest.java
 Wed Nov 23 15:57:52 2016
@@ -44,21 +44,27 @@ public class GcJournalTest {
         File directory = segmentFolder.newFolder();
         GCJournal gc = new GCJournal(directory);
 
-        gc.persist(0, 100);
+        gc.persist(0, 100, 1);
         GCJournalEntry e0 = gc.read();
         assertEquals(100, e0.getRepoSize());
         assertEquals(0, e0.getReclaimedSize());
 
-        gc.persist(0, 250);
+        gc.persist(0, 250, 2);
         GCJournalEntry e1 = gc.read();
         assertEquals(250, e1.getRepoSize());
         assertEquals(0, e1.getReclaimedSize());
-        
-        gc.persist(50, 200);
+
+        gc.persist(50, 200, 3);
         GCJournalEntry e2 = gc.read();
         assertEquals(200, e2.getRepoSize());
         assertEquals(50, e2.getReclaimedSize());
 
+        // same gen
+        gc.persist(75, 300, 3);
+        GCJournalEntry e3 = gc.read();
+        assertEquals(200, e3.getRepoSize());
+        assertEquals(50, e3.getReclaimedSize());
+
         Collection<GCJournalEntry> all = gc.readAll();
         assertEquals(all.size(), 3);
 


Reply via email to