Author: mduerig
Date: Mon Aug  7 13:25:22 2017
New Revision: 1804332

URL: http://svn.apache.org/viewvc?rev=1804332&view=rev
Log:
OAK-6507: Cleanup incorrectly removes base state created by full compaction
Simplify segment reclamation logic

Modified:
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriterPool.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java
    
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/FileStoreBuilder.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/main/java/org/apache/jackrabbit/oak/segment/file/Reclaimers.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GCGeneration.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntry.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV1.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV2.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexWriter.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/OnlineCompactorTest.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/ReclaimersTest.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexLoaderTest.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV1Test.java
    
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV2Test.java

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/DefaultSegmentWriter.java
 Mon Aug  7 13:25:22 2017
@@ -273,7 +273,7 @@ public class DefaultSegmentWriter implem
             checkState(this.writer == null);
             this.writer = writer;
             // FIXME OAK-6519: Properly handle tail compactions in 
deduplication caches
-            int generation = writer.getGeneration().getFull();
+            int generation = writer.getGCGeneration().getGeneration();
             this.stringCache = cacheManager.getStringCache(generation);
             this.templateCache = cacheManager.getTemplateCache(generation);
             this.nodeCache = cacheManager.getNodeCache(generation);
@@ -990,8 +990,8 @@ public class DefaultSegmentWriter implem
         private boolean isOldGeneration(RecordId id) {
             try {
                 GCGeneration thatGen = id.getSegmentId().getGcGeneration();
-                GCGeneration thisGen = writer.getGeneration();
-                return thatGen.compareFull(thisGen) < 0 || 
thatGen.compareTail(thisGen) < 0;
+                GCGeneration thisGen = writer.getGCGeneration();
+                return thatGen.compareWith(thisGen) < 0;
             } catch (SegmentNotFoundException snfe) {
                 // This SNFE means a defer compacted node state is too far
                 // in the past. It has been gc'ed already and cannot be

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
 Mon Aug  7 13:25:22 2017
@@ -123,9 +123,9 @@ public class Segment {
      */
     static final int BLOB_ID_SMALL_LIMIT = 1 << 12;
 
-    static final int GC_TAIL_GENERATION_OFFSET = 4;
+    static final int GC_FULL_GENERATION_OFFSET = 4;
 
-    static final int GC_FULL_GENERATION_OFFSET = 10;
+    static final int GC_GENERATION_OFFSET = 10;
 
     static final int REFERENCED_SEGMENT_ID_COUNT_OFFSET = 14;
 
@@ -373,14 +373,14 @@ public class Segment {
      *
      * @param data         the date of the segment
      * @param segmentId    the id of the segment
-     * @return  the gc generation of this segment or 0 if this is bulk segment.
+     * @return  the gc generation of this segment or {@link GCGeneration#NULL} 
if this is bulk segment.
      */
     @Nonnull
     public static GCGeneration getGcGeneration(ByteBuffer data, UUID 
segmentId) {
         if (isDataSegmentId(segmentId.getLeastSignificantBits())) {
-            int full = data.getInt(GC_FULL_GENERATION_OFFSET);
-            int tail = data.getInt(GC_TAIL_GENERATION_OFFSET);
-            return newGCGeneration(full, tail & 0x7fffffff, tail < 0);
+            int generation = data.getInt(GC_GENERATION_OFFSET);
+            int fullGeneration = data.getInt(GC_FULL_GENERATION_OFFSET);
+            return newGCGeneration(generation, fullGeneration & 0x7fffffff, 
fullGeneration < 0);
         } else {
             return GCGeneration.NULL;
         }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriter.java
 Mon Aug  7 13:25:22 2017
@@ -28,7 +28,7 @@ import static java.lang.System.arraycopy
 import static java.lang.System.currentTimeMillis;
 import static java.lang.System.identityHashCode;
 import static 
org.apache.jackrabbit.oak.segment.Segment.GC_FULL_GENERATION_OFFSET;
-import static 
org.apache.jackrabbit.oak.segment.Segment.GC_TAIL_GENERATION_OFFSET;
+import static org.apache.jackrabbit.oak.segment.Segment.GC_GENERATION_OFFSET;
 import static org.apache.jackrabbit.oak.segment.Segment.HEADER_SIZE;
 import static org.apache.jackrabbit.oak.segment.Segment.RECORD_ID_BYTES;
 import static org.apache.jackrabbit.oak.segment.Segment.RECORD_SIZE;
@@ -109,7 +109,7 @@ public class SegmentBufferWriter impleme
     private final String wid;
 
     @Nonnull
-    private final GCGeneration generation;
+    private final GCGeneration gcGeneration;
 
     /**
      * The segment write buffer, filled from the end to the beginning
@@ -142,14 +142,14 @@ public class SegmentBufferWriter impleme
     public SegmentBufferWriter(@Nonnull SegmentIdProvider idProvider,
                                @Nonnull SegmentReader reader,
                                @CheckForNull String wid,
-                               @Nonnull GCGeneration generation) {
+                               @Nonnull GCGeneration gcGeneration) {
         this.idProvider = checkNotNull(idProvider);
         this.reader = checkNotNull(reader);
         this.wid = (wid == null
                 ? "w-" + identityHashCode(this)
                 : wid);
 
-        this.generation = checkNotNull(generation);
+        this.gcGeneration = checkNotNull(gcGeneration);
     }
 
     @Nonnull
@@ -159,8 +159,8 @@ public class SegmentBufferWriter impleme
     }
 
     @Nonnull
-    GCGeneration getGeneration() {
-        return generation;
+    GCGeneration getGCGeneration() {
+        return gcGeneration;
     }
 
     /**
@@ -184,21 +184,21 @@ public class SegmentBufferWriter impleme
         buffer[4] = 0; // reserved
         buffer[5] = 0; // reserved
 
-        int tail = generation.getTail();
-        if (generation.isTail()) {
-            // Set highest order bit to mark segment created by tail compaction
-            tail |= 0x80000000;
+        int generation = gcGeneration.getGeneration();
+        buffer[GC_GENERATION_OFFSET] = (byte) (generation >> 24);
+        buffer[GC_GENERATION_OFFSET + 1] = (byte) (generation >> 16);
+        buffer[GC_GENERATION_OFFSET + 2] = (byte) (generation >> 8);
+        buffer[GC_GENERATION_OFFSET + 3] = (byte) generation;
+
+        int fullGeneration = gcGeneration.getFullGeneration();
+        if (gcGeneration.isCompacted()) {
+            // Set highest order bit to mark segment created by compaction
+            fullGeneration |= 0x80000000;
         }
-        buffer[GC_TAIL_GENERATION_OFFSET] = (byte) (tail >> 24);
-        buffer[GC_TAIL_GENERATION_OFFSET + 1] = (byte) (tail >> 16);
-        buffer[GC_TAIL_GENERATION_OFFSET + 2] = (byte) (tail >> 8);
-        buffer[GC_TAIL_GENERATION_OFFSET + 3] = (byte) tail;
-
-        int full = generation.getFull();
-        buffer[GC_FULL_GENERATION_OFFSET] = (byte) (full >> 24);
-        buffer[GC_FULL_GENERATION_OFFSET + 1] = (byte) (full >> 16);
-        buffer[GC_FULL_GENERATION_OFFSET + 2] = (byte) (full >> 8);
-        buffer[GC_FULL_GENERATION_OFFSET + 3] = (byte) full;
+        buffer[GC_FULL_GENERATION_OFFSET] = (byte) (fullGeneration >> 24);
+        buffer[GC_FULL_GENERATION_OFFSET + 1] = (byte) (fullGeneration >> 16);
+        buffer[GC_FULL_GENERATION_OFFSET + 2] = (byte) (fullGeneration >> 8);
+        buffer[GC_FULL_GENERATION_OFFSET + 3] = (byte) fullGeneration;
 
         length = 0;
         position = buffer.length;

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriterPool.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriterPool.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriterPool.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBufferWriterPool.java
 Mon Aug  7 13:25:22 2017
@@ -191,7 +191,7 @@ public class SegmentBufferWriterPool imp
                         getWriterId(wid),
                         gcGeneration.get()
                 );
-            } else if (!writer.getGeneration().equals(gcGeneration.get())) {
+            } else if (!writer.getGCGeneration().equals(gcGeneration.get())) {
                 disposed.add(writer);
                 writer = new SegmentBufferWriter(
                         idProvider,

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/AbstractFileStore.java
 Mon Aug  7 13:25:22 2017
@@ -24,7 +24,6 @@ import java.io.Closeable;
 import java.io.File;
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.nio.file.Files;
 import java.util.Collection;
 import java.util.HashSet;
 import java.util.Set;

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=1804332&r1=1804331&r2=1804332&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
 Mon Aug  7 13:25:22 2017
@@ -183,7 +183,7 @@ public class FileStore extends AbstractF
         }
 
         this.segmentWriter = defaultSegmentWriterBuilder("sys")
-                .withGeneration(() -> getGcGeneration().nonTail())
+                .withGeneration(() -> getGcGeneration().nonGC())
                 .withWriterPool()
                 .with(builder.getCacheManager()
                         .withAccessTracking("WRITE", 
builder.getStatsProvider()))

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreBuilder.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreBuilder.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreBuilder.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStoreBuilder.java
 Mon Aug  7 13:25:22 2017
@@ -103,7 +103,7 @@ public class FileStoreBuilder {
             compacted();
             if (cacheManager != null) {
                 // FIXME OAK-6519: Properly handle tail compactions in 
deduplication caches
-                cacheManager.evictOldGeneration(newGeneration.getFull());
+                cacheManager.evictOldGeneration(newGeneration.getGeneration());
             }
         }
 
@@ -111,7 +111,7 @@ public class FileStoreBuilder {
         public void compactionFailed(@Nonnull GCGeneration failedGeneration) {
             if (cacheManager != null) {
                 // FIXME OAK-6519: Properly handle tail compactions in 
deduplication caches
-                cacheManager.evictGeneration(failedGeneration.getFull());
+                cacheManager.evictGeneration(failedGeneration.getGeneration());
             }
         }
     };

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=1804332&r1=1804331&r2=1804332&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
 Mon Aug  7 13:25:22 2017
@@ -176,8 +176,8 @@ public class GCJournal {
                     repoSize,
                     reclaimedSize,
                     ts,
-                    gcGeneration.getFull(),
-                    gcGeneration.getTail(),
+                    gcGeneration.getGeneration(),
+                    gcGeneration.getFullGeneration(),
                     nodes,
                     root
             );
@@ -188,14 +188,15 @@ public class GCJournal {
             long repoSize = parseLong(items, 0);
             long reclaimedSize = parseLong(items, 1);
             long ts = parseLong(items, 2);
-            int fullGeneration = parseInt(items, 3);
-            int tailGeneration = parseInt(items, 4);
+            int generation = parseInt(items, 3);
+            int fullGeneration = parseInt(items, 4);
             long nodes = parseLong(items, 5);
             String root = parseString(items, 6);
             if (root == null) {
                 root = RecordId.NULL.toString10();
             }
-            return new GCJournalEntry(repoSize, reclaimedSize, ts, 
newGCGeneration(fullGeneration, tailGeneration, false), nodes, root);
+            return new GCJournalEntry(repoSize, reclaimedSize, ts,
+                    newGCGeneration(generation, fullGeneration, false), nodes, 
root);
         }
 
         @CheckForNull

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Reclaimers.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Reclaimers.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Reclaimers.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/Reclaimers.java
 Mon Aug  7 13:25:22 2017
@@ -28,44 +28,31 @@ class Reclaimers {
         // Prevent instantiation.
     }
 
-    static Predicate<GCGeneration> newOldReclaimer(@Nonnull final GCGeneration 
reference, int retainedGenerations) {
+    static Predicate<GCGeneration> newOldReclaimer(
+            @Nonnull final GCGeneration referenceGeneration,
+            int retainedGenerations) {
         return new Predicate<GCGeneration>() {
 
             @Override
             public boolean apply(GCGeneration generation) {
-                int deltaFull = reference.compareFull(generation);
-
-                if (deltaFull == 0) {
-                    if (generation.getTail() == 0) {
-                        return false;
-                    }
-
-                    int deltaTail = reference.compareTail(generation);
-
-                    if (deltaTail == 0) {
-                        return false;
-                    }
-
-                    if (deltaTail >= retainedGenerations) {
-                        return !generation.isTail();
-                    }
-
-                    return false;
-                }
+                return isOld(generation) && !sameCompactedTail(generation);
+            }
 
-                if (deltaFull >= retainedGenerations) {
-                    return true;
-                }
+            private boolean isOld(GCGeneration generation) {
+                return referenceGeneration.compareWith(generation) >= 
retainedGenerations;
+            }
 
-                return generation.getTail() != 0;
+            private boolean sameCompactedTail(GCGeneration generation) {
+                return generation.isCompacted()
+                        && generation.getFullGeneration() == 
referenceGeneration.getFullGeneration();
             }
 
             @Override
             public String toString() {
                 return String.format(
                         "(generation older than %d.%d, with %d retained 
generations)",
-                        reference.getFull(),
-                        reference.getTail(),
+                        referenceGeneration.getGeneration(),
+                        referenceGeneration.getFullGeneration(),
                         retainedGenerations
                 );
             }
@@ -73,15 +60,15 @@ class Reclaimers {
         };
     }
 
-    static Predicate<GCGeneration> newExactReclaimer(@Nonnull final 
GCGeneration failedGeneration) {
+    static Predicate<GCGeneration> newExactReclaimer(@Nonnull final 
GCGeneration referenceGeneration) {
         return new Predicate<GCGeneration>() {
             @Override
             public boolean apply(GCGeneration generation) {
-                return generation.equals(failedGeneration);
+                return generation.equals(referenceGeneration);
             }
             @Override
             public String toString() {
-                return "(generation==" + failedGeneration + ")";
+                return "(generation==" + referenceGeneration + ")";
             }
         };
     }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GCGeneration.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GCGeneration.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GCGeneration.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/GCGeneration.java
 Mon Aug  7 13:25:22 2017
@@ -18,97 +18,98 @@
 
 package org.apache.jackrabbit.oak.segment.file.tar;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 import javax.annotation.Nonnull;
 
 import com.google.common.base.Objects;
-
 /**
  * Instances of this class represent the garbage collection generation related
- * information of a segment. Each generation consists of a full and a tail part
- * and a tail flag. The full and tail part are each increased by the respective
- * garbage collection process. In the tail compaction case the segments written
- * by the compactor will also have their tail flag set so cleanup can recognise
- * them as not reclaimable (unless the full part is older then the number of
- * retained generations). Segments written by normal repository writes will
- * inherit the full and tail generations parts of the segments written by the
- * previous compaction process. However the tail flag is never set for such
- * segments ensuring cleanup after subsequent tail compactions can reclaim them
- * once old enough (e.g. the tail part of the generation is older then the
- * number of retained generations).
+ * information of a segment. It consists of the segment's generation, its full
+ * generation and its compaction flag. The segment's generation records the 
number
+ * of garbage collection cycles a segment went through and is incremented with
+ * every garbage collection regardless its type. The segment's full generation
+ * records the number of full garbage collection cycles a segment went through.
+ * It is only incremented on full garbage collection cycles. The segment's 
compaction
+ * flag is set for those segments that have been created by a compaction 
operation.
+ * It is never set for segments created by normal write operations or defer
+ * compactions triggered by such. Segments written by normal repository writes 
will
+ * inherit the generation and full generation of the segment written by the 
previous
+ * compaction process with the compacted flag cleared.
+ * <p>
+ * The information recorded in this way allows to determine the reclamation 
status
+ * of a segment by just looking at the {@code GCGeneration} instances of that 
segment
+ * and of the segment containing the repository head: Let {@code s} be a 
segment,
+ * {@code h} be the segment containing the current repository head and {@code 
n} be
+ * the number of retained generations.
+ * <ul>
+ *     <li>{@code s} is old iff {@code h.generation - s.generation >= n}</li>
+ *     <li>{@code s} is in the same compaction tail than h iff
+ *         {@code s.isCompacted && s.fullGeneration == h.fullGeneration}</li>
+ *     <li>{@code s} is reclaimable iff {@code s} is old and {@code s} is not 
in the same compaction tail than {@code h}</li>
+ * </ul>
  */
 public final class GCGeneration {
 
     public static final GCGeneration NULL = new GCGeneration(0, 0, false);
 
-    public static GCGeneration newGCGeneration(int full, int tail, boolean 
isTail) {
-        return new GCGeneration(full, tail, isTail);
+    public static GCGeneration newGCGeneration(int generation, int 
fullGeneration, boolean isCompacted) {
+        return new GCGeneration(generation, fullGeneration, isCompacted);
     }
 
-    private final int full;
+    private final int generation;
 
-    private final int tail;
+    private final int fullGeneration;
 
-    private final boolean isTail;
+    private final boolean isCompacted;
 
-    private GCGeneration(int full, int tail, boolean isTail) {
-        this.full = full;
-        this.tail = tail;
-        this.isTail = isTail;
+    private GCGeneration(int generation, int fullGeneration, boolean 
isCompacted) {
+        this.generation = generation;
+        this.fullGeneration = fullGeneration;
+        this.isCompacted = isCompacted;
     }
 
-    public int getFull() {
-        return full;
+    public int getGeneration() {
+        return generation;
     }
 
-    public int getTail() {
-        return tail;
+    public int getFullGeneration() {
+        return fullGeneration;
     }
 
-    public boolean isTail() {
-        return isTail;
+    public boolean isCompacted() {
+        return isCompacted;
     }
 
     /**
-     * Create a new instance with the full part incremented by one and the tail
-     * part and the tail flag left unchanged.
+     * Create a new instance with the generation and the full generation 
incremented by one
+     * and the compaction flag left unchanged.
      */
     @Nonnull
     public GCGeneration nextFull() {
-        return new GCGeneration(full + 1, 0, false);
+        return new GCGeneration(generation + 1, fullGeneration + 1, true);
     }
 
     /**
-     * Create a new instance with the tail part incremented by one and the full
-     * part and the tail flag left unchanged.
+     * Create a new instance with the generation incremented by one and the 
full
+     * generation and the compaction flag left unchanged.
      */
     @Nonnull
     public GCGeneration nextTail() {
-        return new GCGeneration(full, tail + 1, true);
+        return new GCGeneration(generation + 1, fullGeneration, true);
     }
 
     /**
-     * Create a new instance with the tail flag unset and the full part and 
tail
-     * part left unchanged.
+     * Create a new instance with the compaction flag unset and the generation 
and the
+     * full generation left unchanged.
      */
     @Nonnull
-    public GCGeneration nonTail() {
-        return new GCGeneration(full, tail, false);
-    }
-
-    /**
-     * The the difference of the full part between {@code this} and {@code
-     * that}.
-     */
-    public int compareFull(@Nonnull GCGeneration that) {
-        return full - that.full;
+    public GCGeneration nonGC() {
+        return new GCGeneration(generation, fullGeneration, false);
     }
 
-    /**
-     * The the difference of the tail part between {@code this} and {@code
-     * that}.
-     */
-    public int compareTail(@Nonnull GCGeneration that) {
-        return tail - that.tail;
+    public int compareWith(@Nonnull GCGeneration gcGeneration) {
+        return generation - checkNotNull(gcGeneration).generation;
     }
 
     @Override
@@ -120,20 +121,22 @@ public final class GCGeneration {
             return false;
         }
         GCGeneration that = (GCGeneration) other;
-        return full == that.full && tail == that.tail && isTail == that.isTail;
+        return generation == that.generation
+                && fullGeneration == that.fullGeneration
+                && isCompacted == that.isCompacted;
     }
 
     @Override
     public int hashCode() {
-        return Objects.hashCode(full, tail, isTail);
+        return Objects.hashCode(generation, fullGeneration, isCompacted);
     }
 
     @Override
     public String toString() {
         return "GCGeneration{" +
-                "full=" + full + ',' +
-                "tail=" + tail +  ',' +
-                "isTail=" + isTail + '}';
+                "generation=" + generation + ',' +
+                "fullGeneration=" + fullGeneration +  ',' +
+                "isCompacted=" + isCompacted + '}';
     }
 
 }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarReader.java
 Mon Aug  7 13:25:22 2017
@@ -553,9 +553,9 @@ class TarReader implements Closeable {
                     e.getPosition(),
                     e.getLength(),
                     newGCGeneration(
+                            e.getGeneration(),
                             e.getFullGeneration(),
-                            e.getTailGeneration(),
-                            e.isTail()
+                            e.isCompacted()
                     )
             );
         }
@@ -949,9 +949,9 @@ class TarReader implements Closeable {
         Map<GCGeneration, Map<UUID, Set<String>>> binaryReferences = 
newHashMapWithExpectedSize(nGenerations);
 
         for (int i = 0; i < nGenerations; i++) {
+            int generation = buffer.getInt();
             int fullGeneration = buffer.getInt();
-            int tailGeneration = buffer.getInt();
-            boolean isTail = buffer.get() != 0;
+            boolean isCompacted = buffer.get() != 0;
             int segmentCount = buffer.getInt();
 
             Map<UUID, Set<String>> segments = 
newHashMapWithExpectedSize(segmentCount);
@@ -975,7 +975,7 @@ class TarReader implements Closeable {
                 segments.put(new UUID(msb, lsb), references);
             }
 
-            binaryReferences.put(newGCGeneration(fullGeneration, 
tailGeneration, isTail), segments);
+            binaryReferences.put(newGCGeneration(generation, fullGeneration, 
isCompacted), segments);
         }
 
         return binaryReferences;

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/TarWriter.java
 Mon Aug  7 13:25:22 2017
@@ -377,9 +377,9 @@ class TarWriter implements Closeable {
             GCGeneration generation = be.getKey();
             Map<UUID, Set<String>> segmentToReferences = be.getValue();
 
-            buffer.putInt(generation.getFull());
-            buffer.putInt(generation.getTail());
-            buffer.put((byte) (generation.isTail() ? 1 : 0));
+            buffer.putInt(generation.getGeneration());
+            buffer.putInt(generation.getFullGeneration());
+            buffer.put((byte) (generation.isCompacted() ? 1 : 0));
             buffer.putInt(segmentToReferences.size());
 
             for (Entry<UUID, Set<String>> se : segmentToReferences.entrySet()) 
{
@@ -499,9 +499,9 @@ class TarWriter implements Closeable {
                     entry.lsb(),
                     entry.offset(),
                     entry.size(),
-                    entry.generation().getFull(),
-                    entry.generation().getTail(),
-                    entry.generation().isTail()
+                    entry.generation().getGeneration(),
+                    entry.generation().getFullGeneration(),
+                    entry.generation().isCompacted()
             );
         }
 

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntry.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntry.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntry.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntry.java
 Mon Aug  7 13:25:22 2017
@@ -51,26 +51,24 @@ public interface IndexEntry {
     int getLength();
 
     /**
-     * Return the full generation of this entry.
+     * Return the generation of this entry.
      *
-     * @return the full generation of this entry.
+     * @return the generation of this entry.
      */
-    int getFullGeneration();
+    int getGeneration();
 
     /**
-     * Return the tail generation of this entry.
+     * Return the full generation of this entry.
      *
-     * @return the tail generation of this entry.
+     * @return the full generation of this entry.
      */
-    int getTailGeneration();
+    int getFullGeneration();
 
     /**
-     * Return {@code true} if this entry was generated as part of a tail
-     * commit.
+     * Return {@code true} if this entry was generated by a compaction 
operation.
      *
-     * @return {@code true} if this entry was generated as part of a tail
-     * commit.
+     * @return {@code true} if this entry was generated by a compaction 
operation.
      */
-    boolean isTail();
+    boolean isCompacted();
 
 }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV1.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV1.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV1.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV1.java
 Mon Aug  7 13:25:22 2017
@@ -53,17 +53,17 @@ class IndexEntryV1 implements IndexEntry
     }
 
     @Override
-    public int getFullGeneration() {
+    public int getGeneration() {
         return index.getInt(position + 24);
     }
 
     @Override
-    public int getTailGeneration() {
+    public int getFullGeneration() {
         return 0;
     }
 
     @Override
-    public boolean isTail() {
+    public boolean isCompacted() {
         return false;
     }
 

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV2.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV2.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV2.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexEntryV2.java
 Mon Aug  7 13:25:22 2017
@@ -53,17 +53,17 @@ class IndexEntryV2 implements IndexEntry
     }
 
     @Override
-    public int getFullGeneration() {
+    public int getGeneration() {
         return index.getInt(position + 24);
     }
 
     @Override
-    public int getTailGeneration() {
+    public int getFullGeneration() {
         return index.getInt(position + 28);
     }
 
     @Override
-    public boolean isTail() {
+    public boolean isCompacted() {
         return index.get(position + 32) != 0;
     }
 

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexWriter.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexWriter.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexWriter.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexWriter.java
 Mon Aug  7 13:25:22 2017
@@ -40,11 +40,11 @@ public class IndexWriter {
 
         int size;
 
-        int fullGeneration;
+        int generation;
 
-        int tailGeneration;
+        int fullGeneration;
 
-        boolean isTail;
+        boolean isCompacted;
 
     }
 
@@ -83,15 +83,15 @@ public class IndexWriter {
      * @param isTail         Whether the entry is generated as part of a tail
      *                       commit.
      */
-    public void addEntry(long msb, long lsb, int offset, int size, int 
fullGeneration, int tailGeneration, boolean isTail) {
+    public void addEntry(long msb, long lsb, int offset, int size, int 
generation, int fullGeneration, boolean isCompacted) {
         Entry entry = new Entry();
         entry.msb = msb;
         entry.lsb = lsb;
         entry.offset = offset;
         entry.size = size;
+        entry.generation = generation;
         entry.fullGeneration = fullGeneration;
-        entry.tailGeneration = tailGeneration;
-        entry.isTail = isTail;
+        entry.isCompacted = isCompacted;
         entries.add(entry);
     }
 
@@ -130,9 +130,9 @@ public class IndexWriter {
             buffer.putLong(entry.lsb);
             buffer.putInt(entry.offset);
             buffer.putInt(entry.size);
+            buffer.putInt(entry.generation);
             buffer.putInt(entry.fullGeneration);
-            buffer.putInt(entry.tailGeneration);
-            buffer.put((byte) (entry.isTail ? 1 : 0));
+            buffer.put((byte) (entry.isCompacted ? 1 : 0));
         }
 
         CRC32 checksum = new CRC32();

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/main/java/org/apache/jackrabbit/oak/segment/standby/client/StandbyClientSync.java
 Mon Aug  7 13:25:22 2017
@@ -157,7 +157,7 @@ public final class StandbyClientSync imp
                     new StandbyClientSyncExecution(fileStore, client, 
newRunningSupplier()).execute();
                     GCGeneration genAfter = headGeneration(fileStore);
 
-                    if (autoClean && (genAfter.compareFull(genBefore)) > 0 || 
genAfter.compareTail(genBefore) > 0) {
+                    if (autoClean && (genAfter.compareWith(genBefore)) > 0) {
                         log.info("New head generation detected (prevHeadGen: 
{} newHeadGen: {}), running cleanup.", genBefore, genAfter);
                         cleanupAndRemove();
                     }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/CompactionAndCleanupIT.java
 Mon Aug  7 13:25:22 2017
@@ -1156,7 +1156,7 @@ public class CompactionAndCleanupIT {
             builder.getChildNode("a").remove();
             NodeState deferCompacted = nodeStore.merge(builder, 
EmptyHook.INSTANCE, CommitInfo.EMPTY);
             assertEquals(
-                    uncompacted.getSegment().getGcGeneration().nextFull(),
+                    
uncompacted.getSegment().getGcGeneration().nextFull().nonGC(),
                     
((SegmentNodeState)deferCompacted).getSegment().getGcGeneration());
         }
     }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/OnlineCompactorTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/OnlineCompactorTest.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/OnlineCompactorTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/OnlineCompactorTest.java
 Mon Aug  7 13:25:22 2017
@@ -121,7 +121,7 @@ public class OnlineCompactorTest {
     @Nonnull
     private static OnlineCompactor createCompactor(FileStore fileStore, 
Supplier<Boolean> cancel) {
         SegmentWriter writer = defaultSegmentWriterBuilder("c")
-                .withGeneration(newGCGeneration(1, 0, false))
+                .withGeneration(newGCGeneration(1, 1, true))
                 .build(fileStore);
         return new OnlineCompactor(fileStore.getReader(), writer, 
fileStore.getBlobStore(), cancel, () -> {});
     }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/ReclaimersTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/ReclaimersTest.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/ReclaimersTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/ReclaimersTest.java
 Mon Aug  7 13:25:22 2017
@@ -17,6 +17,7 @@
 
 package org.apache.jackrabbit.oak.segment.file;
 
+import static 
org.apache.jackrabbit.oak.segment.file.Reclaimers.newExactReclaimer;
 import static 
org.apache.jackrabbit.oak.segment.file.Reclaimers.newOldReclaimer;
 import static 
org.apache.jackrabbit.oak.segment.file.tar.GCGeneration.newGCGeneration;
 import static org.junit.Assert.assertFalse;
@@ -29,51 +30,81 @@ import org.junit.Test;
 public class ReclaimersTest {
 
     @Test
-    public void testOldReclaimer() throws Exception {
-        Predicate<GCGeneration> p = newOldReclaimer(newGCGeneration(3, 3, 
false), 2);
-
-        // Segments from the same full and tail generation should not be
-        // removed.
-
-        assertFalse(p.apply(newGCGeneration(3, 3, false)));
-        assertFalse(p.apply(newGCGeneration(3, 3, true)));
-
-        // Recent segments, tail or not-tail ones, can't be removed.
-
-        assertFalse(p.apply(newGCGeneration(3, 2, false)));
-        assertFalse(p.apply(newGCGeneration(3, 2, true)));
-
-        // Old segments from the same full generation can be removed as long
-        // as they are not tail segments.
-
-        assertTrue(p.apply(newGCGeneration(3, 1, false)));
-        assertFalse(p.apply(newGCGeneration(3, 1, true)));
-
-        // A full head state from the same full generation can't be removed.
-
-        assertFalse(p.apply(newGCGeneration(3, 0, false)));
-
-        // Some of these generations can be reclaimed, some may not. Since 
there
-        // is a new full head state with full generation 3, every tail and
-        // non-tail segment with a tail generation greater than zero can be
-        // removed. The full head state with full generation 2 can't be 
removed,
-        // otherwise the condition about the number of retained generations
-        // would be violated.
-
-        assertTrue(p.apply(newGCGeneration(2, 2, false)));
-        assertTrue(p.apply(newGCGeneration(2, 2, true)));
-        assertTrue(p.apply(newGCGeneration(2, 1, false)));
-        assertTrue(p.apply(newGCGeneration(2, 1, true)));
-        assertFalse(p.apply(newGCGeneration(2, 0, false)));
-
-        // These generations can be reclaimed because their full generation is
-        // too old when compared to the number of retained generations.
+    public void testOldReclaimerCompactedHead() {
+        Predicate<GCGeneration> reclaimer = newOldReclaimer(
+                newGCGeneration(3, 3, true), 2);
+
+        // Don't reclaim young segments
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, true)));
+
+        // Reclaim old and uncompacted segments
+        assertTrue(reclaimer.apply(newGCGeneration(1, 3, false)));
+        assertTrue(reclaimer.apply(newGCGeneration(1, 3, false)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 3, false)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 3, false)));
+
+        // Don't reclaim old compacted segments from the same full generation
+        assertFalse(reclaimer.apply(newGCGeneration(1, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(1, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(0, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(0, 3, true)));
+
+        // Reclaim old compacted segments from prior full generations
+        assertTrue(reclaimer.apply(newGCGeneration(1, 2, true)));
+        assertTrue(reclaimer.apply(newGCGeneration(1, 2, true)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 2, true)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 2, true)));
+    }
 
-        assertTrue(p.apply(newGCGeneration(1, 2, false)));
-        assertTrue(p.apply(newGCGeneration(1, 2, true)));
-        assertTrue(p.apply(newGCGeneration(1, 1, false)));
-        assertTrue(p.apply(newGCGeneration(1, 1, true)));
-        assertTrue(p.apply(newGCGeneration(1, 0, false)));
+    @Test
+    public void testOldReclaimerUncompactedHead() {
+        Predicate<GCGeneration> reclaimer = newOldReclaimer(
+                newGCGeneration(3, 3, true), 2);
+
+        // Don't reclaim young segments
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, true)));
+
+        // Reclaim old and uncompacted segments
+        assertTrue(reclaimer.apply(newGCGeneration(1, 3, false)));
+        assertTrue(reclaimer.apply(newGCGeneration(1, 3, false)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 3, false)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 3, false)));
+
+        // Don't reclaim old compacted segments from the same full generation
+        assertFalse(reclaimer.apply(newGCGeneration(1, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(1, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(0, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(0, 3, true)));
+
+        // Reclaim old compacted segments from prior full generations
+        assertTrue(reclaimer.apply(newGCGeneration(1, 2, true)));
+        assertTrue(reclaimer.apply(newGCGeneration(1, 2, true)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 2, true)));
+        assertTrue(reclaimer.apply(newGCGeneration(0, 2, true)));
     }
 
+    @Test
+    public void testExactReclaimer() {
+        Predicate<GCGeneration> reclaimer = newExactReclaimer(
+                newGCGeneration(3, 3, false));
+
+        assertTrue(reclaimer.apply(newGCGeneration(3, 3, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 3, true)));
+        assertFalse(reclaimer.apply(newGCGeneration(3, 2, false)));
+        assertFalse(reclaimer.apply(newGCGeneration(2, 3, false)));
+    }
 }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexLoaderTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexLoaderTest.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexLoaderTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexLoaderTest.java
 Mon Aug  7 13:25:22 2017
@@ -41,9 +41,9 @@ public class IndexLoaderTest {
         assertEquals(lsb, entry.getLsb());
         assertEquals(position, entry.getPosition());
         assertEquals(length, entry.getLength());
-        assertEquals(full, entry.getFullGeneration());
-        assertEquals(tail, entry.getTailGeneration());
-        assertEquals(isTail, entry.isTail());
+        assertEquals(full, entry.getGeneration());
+        assertEquals(tail, entry.getFullGeneration());
+        assertEquals(isTail, entry.isCompacted());
     }
 
     @Test(expected = InvalidIndexException.class)

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV1Test.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV1Test.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV1Test.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV1Test.java
 Mon Aug  7 13:25:22 2017
@@ -86,9 +86,9 @@ public class IndexV1Test {
         assertEquals(2, entry.getLsb());
         assertEquals(3, entry.getPosition());
         assertEquals(4, entry.getLength());
-        assertEquals(5, entry.getFullGeneration());
-        assertEquals(0, entry.getTailGeneration());
-        assertEquals(false, entry.isTail());
+        assertEquals(5, entry.getGeneration());
+        assertEquals(0, entry.getFullGeneration());
+        assertEquals(false, entry.isCompacted());
     }
 
 }

Modified: 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV2Test.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV2Test.java?rev=1804332&r1=1804331&r2=1804332&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV2Test.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-tar/src/test/java/org/apache/jackrabbit/oak/segment/file/tar/index/IndexV2Test.java
 Mon Aug  7 13:25:22 2017
@@ -86,9 +86,9 @@ public class IndexV2Test {
         assertEquals(2, entry.getLsb());
         assertEquals(3, entry.getPosition());
         assertEquals(4, entry.getLength());
-        assertEquals(5, entry.getFullGeneration());
-        assertEquals(6, entry.getTailGeneration());
-        assertEquals(true, entry.isTail());
+        assertEquals(5, entry.getGeneration());
+        assertEquals(6, entry.getFullGeneration());
+        assertEquals(true, entry.isCompacted());
     }
 
 }


Reply via email to