Author: mduerig
Date: Wed Apr 27 10:00:52 2016
New Revision: 1741194

URL: http://svn.apache.org/viewvc?rev=1741194&view=rev
Log:
OAK-4312: Fix test failures in SegmentDataStoreBlobGCIT
Collect blob references by looking at the tar files and its segments instead of 
following the reference graph from the gc roots

Modified:
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlobReferenceRetriever.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentTracker.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
    
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/TarReader.java
    
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/ExternalBlobIT.java
    
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/SegmentDataStoreBlobGCIT.java

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/Segment.java
 Wed Apr 27 10:00:52 2016
@@ -425,7 +425,7 @@ public class Segment {
         }
     }
 
-    void collectBlobReferences(ReferenceCollector collector) {
+    public void collectBlobReferences(ReferenceCollector collector) {
         int refcount = getRefCount();
         int rootcount =
                 data.getShort(data.position() + ROOT_COUNT_OFFSET) & 0xffff;

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlobReferenceRetriever.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlobReferenceRetriever.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlobReferenceRetriever.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentBlobReferenceRetriever.java
 Wed Apr 27 10:00:52 2016
@@ -19,8 +19,11 @@
 
 package org.apache.jackrabbit.oak.segment;
 
+import java.io.IOException;
+
 import org.apache.jackrabbit.oak.plugins.blob.BlobReferenceRetriever;
 import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
+import org.apache.jackrabbit.oak.segment.file.FileStore;
 
 /**
  * Implementation of {@link BlobReferenceRetriever} to retrieve blob 
references from the
@@ -28,15 +31,20 @@ import org.apache.jackrabbit.oak.plugins
  */
 public class SegmentBlobReferenceRetriever implements BlobReferenceRetriever {
 
-    private final SegmentTracker tracker;
+    private final FileStore store;
 
-    public SegmentBlobReferenceRetriever(SegmentTracker tracker) {
-        this.tracker = tracker;
+    public SegmentBlobReferenceRetriever(FileStore store) {
+        this.store = store;
     }
 
     @Override
     public void collectReferences(final ReferenceCollector collector) {
-        tracker.collectBlobReferences(collector);
+        try {
+            store.collectBlobReferences(collector);
+        } catch (IOException e) {
+            // FIXME OAK-4314: BlobReferenceRetriever#collectReferences should 
allow exceptions
+            throw new IllegalStateException(e);
+        }
     }
 }
 

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentNodeStoreService.java
 Wed Apr 27 10:00:52 2016
@@ -504,7 +504,7 @@ public class SegmentNodeStoreService ext
 
         if (store.getBlobStore() instanceof GarbageCollectableBlobStore) {
             BlobGarbageCollector gc = new MarkSweepGarbageCollector(
-                    new SegmentBlobReferenceRetriever(store.getTracker()),
+                    new SegmentBlobReferenceRetriever(store),
                     (GarbageCollectableBlobStore) store.getBlobStore(),
                     executor,
                     TimeUnit.SECONDS.toMillis(blobGcMaxAgeInSecs),

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentTracker.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentTracker.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentTracker.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/SegmentTracker.java
 Wed Apr 27 10:00:52 2016
@@ -19,13 +19,10 @@
 package org.apache.jackrabbit.oak.segment;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.Queues.newArrayDeque;
 import static com.google.common.collect.Sets.newHashSet;
 import static java.lang.Boolean.getBoolean;
 
-import java.io.IOException;
 import java.security.SecureRandom;
-import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -38,7 +35,6 @@ import com.google.common.cache.RemovalCa
 import org.apache.jackrabbit.oak.cache.CacheLIRS;
 import org.apache.jackrabbit.oak.cache.CacheLIRS.EvictionCallback;
 import org.apache.jackrabbit.oak.cache.CacheStats;
-import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
 import org.apache.jackrabbit.oak.segment.file.FileStore;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -274,42 +270,6 @@ public class SegmentTracker {
     }
 
     /**
-     * Finds all external blob references that are currently accessible
-     * in this repository and adds them to the given collector. Useful
-     * for collecting garbage in an external data store.
-     * <p>
-     * Note that this method only collects blob references that are already
-     * stored in the repository (at the time when this method is called), so
-     * the garbage collector will need some other mechanism for tracking
-     * in-memory references and references stored while this method is
-     * running.
-     */
-    public void collectBlobReferences(ReferenceCollector collector) {
-        try {
-            Set<SegmentId> processed = newHashSet();
-            Queue<SegmentId> queue = newArrayDeque(getReferencedSegmentIds());
-            writer.flush(); // force the current segment to have root record 
info
-            while (!queue.isEmpty()) {
-                SegmentId id = queue.remove();
-                if (id.isDataSegmentId() && processed.add(id)) {
-                    Segment segment = id.getSegment();
-
-                    segment.collectBlobReferences(collector);
-
-                    for (SegmentId refid : segment.getReferencedIds()) {
-                        if (refid.isDataSegmentId() && 
!processed.contains(refid)) {
-                            queue.add(refid);
-                        }
-                    }
-                }
-            }
-        } catch (IOException e) {
-            log.error("Error while flushing pending segments", e);
-            throw new IllegalStateException("Unexpected IOException", e);
-        }
-    }
-
-    /**
      * 
      * @param msb
      * @param lsb

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/FileStore.java
 Wed Apr 27 10:00:52 2016
@@ -67,6 +67,7 @@ import com.google.common.base.Stopwatch;
 import com.google.common.base.Supplier;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.plugins.blob.BlobStoreBlob;
+import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
 import org.apache.jackrabbit.oak.segment.RecordCache;
 import org.apache.jackrabbit.oak.segment.RecordCache.DeduplicationCache;
 import org.apache.jackrabbit.oak.segment.RecordId;
@@ -963,6 +964,36 @@ public class FileStore implements Segmen
     }
 
     /**
+     * Finds all external blob references that are currently accessible
+     * in this repository and adds them to the given collector. Useful
+     * for collecting garbage in an external data store.
+     * <p>
+     * Note that this method only collects blob references that are already
+     * stored in the repository (at the time when this method is called), so
+     * the garbage collector will need some other mechanism for tracking
+     * in-memory references and references stored while this method is
+     * running.
+     * @param collector  reference collector called back for each blob 
reference found
+     */
+    public void collectBlobReferences(ReferenceCollector collector) throws 
IOException {
+        tracker.getWriter().flush();
+        List<TarReader> tarReaders = newArrayList();
+        fileStoreLock.writeLock().lock();
+        try {
+            newWriter();
+            tarReaders.addAll(this.readers);
+        } finally {
+            fileStoreLock.writeLock().unlock();
+        }
+
+        // FIXME OAK-4282: Make the number of retained gc generation 
configurable
+        int generation = getGcGen() - 1;
+        for (TarReader tarReader : tarReaders) {
+            tarReader.collectBlobReferences(tracker, collector, generation);
+        }
+    }
+
+    /**
      * Returns the cancellation policy for the compaction phase. If the disk
      * space was considered insufficient at least once during compaction (or if
      * the space was never sufficient to begin with), compaction is considered

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/TarReader.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/TarReader.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/TarReader.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/main/java/org/apache/jackrabbit/oak/segment/file/TarReader.java
 Wed Apr 27 10:00:52 2016
@@ -54,7 +54,10 @@ import java.util.zip.CRC32;
 import javax.annotation.Nonnull;
 
 import org.apache.commons.io.FileUtils;
+import org.apache.jackrabbit.oak.plugins.blob.ReferenceCollector;
 import org.apache.jackrabbit.oak.segment.SegmentGraph.SegmentGraphVisitor;
+import org.apache.jackrabbit.oak.segment.SegmentId;
+import org.apache.jackrabbit.oak.segment.SegmentTracker;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -728,6 +731,17 @@ class TarReader implements Closeable {
             }
         }
     }
+
+    void collectBlobReferences(SegmentTracker tracker, ReferenceCollector 
collector, int generation) {
+        for (TarEntry entry : getEntries()) {
+            if (entry.generation() >= generation) {
+                // FIXME OAK-4201: Add an index of binary references in a tar 
file
+                // Fetch the blob references from the tar index instead 
reading them from the segment
+                SegmentId id = tracker.getSegmentId(entry.msb(), entry.lsb());
+                id.getSegment().collectBlobReferences(collector);
+            }
+        }
+    }
 
     void mark(Set<UUID> bulkRefs, Set<UUID> reclaim, int generation) throws 
IOException {
         Map<UUID, List<UUID>> graph = getGraph(true);

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/ExternalBlobIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/ExternalBlobIT.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/ExternalBlobIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/ExternalBlobIT.java
 Wed Apr 27 10:00:52 2016
@@ -61,7 +61,7 @@ import org.junit.rules.TemporaryFolder;
 
 public class ExternalBlobIT {
 
-    private SegmentStore store;
+    private FileStore store;
     private SegmentNodeStore nodeStore;
     private FileBlob fileBlob;
 
@@ -123,7 +123,7 @@ public class ExternalBlobIT {
         nodeStore.merge(nb, EmptyHook.INSTANCE, CommitInfo.EMPTY);
 
         final List<String> refrences = Lists.newArrayList();
-        store.getTracker().collectBlobReferences(new ReferenceCollector() {
+        store.collectBlobReferences(new ReferenceCollector() {
             @Override
             public void addReference(String reference, String nodeId) {
                 assertNotNull(reference);

Modified: 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/SegmentDataStoreBlobGCIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/SegmentDataStoreBlobGCIT.java?rev=1741194&r1=1741193&r2=1741194&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/SegmentDataStoreBlobGCIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment-next/src/test/java/org/apache/jackrabbit/oak/segment/SegmentDataStoreBlobGCIT.java
 Wed Apr 27 10:00:52 2016
@@ -67,7 +67,6 @@ import org.apache.jackrabbit.oak.spi.com
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.junit.After;
 import org.junit.BeforeClass;
-import org.junit.Ignore;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
@@ -177,7 +176,12 @@ public class SegmentDataStoreBlobGCIT {
 
         // Sleep a little to make eligible for cleanup
         TimeUnit.MILLISECONDS.sleep(5);
-        store.maybeCompact(false);
+
+        // FIXME OAK-4282: Make the number of retained gc generation 
configurable
+        // Need to compact twice because of the generation cleanup threshold
+        // (currently hard coded to 2);
+        store.compact();
+        store.compact();
         store.cleanup();
 
         return state;
@@ -207,9 +211,7 @@ public class SegmentDataStoreBlobGCIT {
         nodeStore.merge(builder, EmptyHook.INSTANCE, CommitInfo.EMPTY);
     }
 
-    // FIXME OAK-4312: Fix test failures in SegmentDataStoreBlobGCIT
     @Test
-    @Ignore
     public void gc() throws Exception {
         DataStoreState state = setUp();
         log.info("{} blobs that should remain after gc : {}", 
state.blobsPresent.size(), state.blobsPresent);
@@ -237,9 +239,7 @@ public class SegmentDataStoreBlobGCIT {
         assertEquals(0, candidates);
     }
 
-    // FIXME OAK-4312: Fix test failures in SegmentDataStoreBlobGCIT
     @Test
-    @Ignore
     public void consistencyCheckWithGc() throws Exception {
         DataStoreState state = setUp();
         Set<String> existingAfterGC = gcInternal(0);
@@ -269,9 +269,7 @@ public class SegmentDataStoreBlobGCIT {
         assertEquals(count, candidates);
     }
 
-    // FIXME OAK-4312: Fix test failures in SegmentDataStoreBlobGCIT
     @Test
-    @Ignore
     public void gcLongRunningBlobCollection() throws Exception {
         DataStoreState state = setUp();
         log.info("{} Blobs added {}", state.blobsAdded.size(), 
state.blobsAdded);
@@ -286,7 +284,7 @@ public class SegmentDataStoreBlobGCIT {
                 REPOSITORY.getNameFromId(repoId));
         }
         TestGarbageCollector gc = new TestGarbageCollector(
-            new SegmentBlobReferenceRetriever(store.getTracker()),
+            new SegmentBlobReferenceRetriever(store),
             (GarbageCollectableBlobStore) store.getBlobStore(), executor, 
folder.newFolder().getAbsolutePath(), 5, 5000, repoId);
         gc.collectGarbage(false);
         Set<String> existingAfterGC = iterate();
@@ -296,9 +294,7 @@ public class SegmentDataStoreBlobGCIT {
         assertEquals(gc.additionalBlobs, 
Sets.symmetricDifference(state.blobsPresent, existingAfterGC));
     }
 
-    // FIXME OAK-4312: Fix test failures in SegmentDataStoreBlobGCIT
     @Test
-    @Ignore
     public void gcWithInlined() throws Exception {
         blobStore = new DataStoreBlobStore(DataStoreUtils.createFDS(new 
File(getWorkDir(), "datastore"), 16516));
         DataStoreState state = setUp();
@@ -341,7 +337,7 @@ public class SegmentDataStoreBlobGCIT {
                 REPOSITORY.getNameFromId(repoId));
         }
         MarkSweepGarbageCollector gc = new MarkSweepGarbageCollector(
-            new SegmentBlobReferenceRetriever(store.getTracker()),
+            new SegmentBlobReferenceRetriever(store),
             (GarbageCollectableBlobStore) store.getBlobStore(), executor, 
folder.newFolder().getAbsolutePath(), 2048, blobGcMaxAgeInSecs,
             repoId);
         return gc;


Reply via email to