Author: amitj
Date: Tue Jul 26 07:38:47 2016
New Revision: 1754076

URL: http://svn.apache.org/viewvc?rev=1754076&view=rev
Log:
OAK-4597:  Improve test coverage of blob GC

Added test for mark phase GC to check blob references returned

Modified:
    
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoBlobGCTest.java
    
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentDataStoreBlobGCIT.java

Modified: 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoBlobGCTest.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoBlobGCTest.java?rev=1754076&r1=1754075&r2=1754076&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoBlobGCTest.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/MongoBlobGCTest.java
 Tue Jul 26 07:38:47 2016
@@ -84,10 +84,14 @@ public class MongoBlobGCTest extends Abs
     public TemporaryFolder folder = new TemporaryFolder(new File("target"));
 
     public DataStoreState setUp(boolean deleteDirect) throws Exception {
+        return setUp(deleteDirect, 10);
+    }
+
+    public DataStoreState setUp(boolean deleteDirect, int count) throws 
Exception {
         DocumentNodeStore s = mk.getNodeStore();
         NodeBuilder a = s.getRoot().builder();
 
-        int number = 10;
+        int number = count;
         int maxDeleted = 5;
         // track the number of the assets to be deleted
         List<Integer> processed = Lists.newArrayList();
@@ -193,6 +197,27 @@ public class MongoBlobGCTest extends Abs
         assertTrue(Sets.symmetricDifference(state.blobsPresent, 
existingAfterGC).isEmpty());
     }
 
+
+    @Test
+    public void checkMark() throws Exception {
+        LogCustomizer customLogs = LogCustomizer
+            .forLogger(MarkSweepGarbageCollector.class.getName())
+            .enable(Level.TRACE)
+            .filter(Level.TRACE)
+            .create();
+
+        DataStoreState state = setUp(true, 1000);
+        log.info("{} blobs available : {}", state.blobsPresent.size(), 
state.blobsPresent);
+        customLogs.starting();
+        ThreadPoolExecutor executor = (ThreadPoolExecutor) 
Executors.newFixedThreadPool(10);
+        String rootFolder = folder.newFolder().getAbsolutePath();
+        MarkSweepGarbageCollector gcObj = init(0, executor, rootFolder);
+        gcObj.collectGarbage(true);
+        customLogs.finished();
+
+        assertBlobReferences(state.blobsPresent, rootFolder);
+    }
+
     @Test
     public void gcSpecialChar() throws Exception {
         DataStoreState state = setUp(true);
@@ -358,28 +383,42 @@ public class MongoBlobGCTest extends Abs
         assertBlobReferenceRecords(2, rootFolder);
     }
 
+    private static void assertBlobReferences(Set<String> expected, String 
rootFolder) throws IOException {
+        InputStream is = null;
+        try {
+            is = new FileInputStream(getMarkedFile(rootFolder));
+            Set<String> records = FileIOUtils.readStringsAsSet(is, true);
+            assertEquals(expected, records);
+        } finally {
+            Closeables.close(is, false);
+        }
+    }
+
     private static void assertBlobReferenceRecords(int expected, String 
rootFolder) throws IOException {
-        // Read the marked files to check if paths logged or not
-        File root = new File(rootFolder);
-        List<File> rootFile = FileFilterUtils.filterList(
-            FileFilterUtils.prefixFileFilter("gcworkdir-"),
-            root.listFiles());
-        List<File> markedFiles = FileFilterUtils.filterList(
-            FileFilterUtils.prefixFileFilter("marked-"),
-            rootFile.get(0).listFiles());
         InputStream is = null;
         try {
-            is = new FileInputStream(markedFiles.get(0));
+            is = new FileInputStream(getMarkedFile(rootFolder));
             Set<String> records = FileIOUtils.readStringsAsSet(is, true);
             for (String rec : records) {
                 assertEquals(expected, 
Splitter.on(",").omitEmptyStrings().splitToList(rec).size());
             }
         } finally {
             Closeables.close(is, false);
-            FileUtils.forceDelete(rootFile.get(0));
         }
     }
 
+    private static File getMarkedFile(String rootFolder) {
+        // Read the marked files to check if paths logged or not
+        File root = new File(rootFolder);
+        List<File> rootFile = FileFilterUtils.filterList(
+            FileFilterUtils.prefixFileFilter("gcworkdir-"),
+            root.listFiles());
+        List<File> markedFiles = FileFilterUtils.filterList(
+            FileFilterUtils.prefixFileFilter("marked-"),
+            rootFile.get(0).listFiles());
+        return markedFiles.get(0);
+    }
+
     private Set<String> gc(int blobGcMaxAgeInSecs) throws Exception {
         ThreadPoolExecutor executor = (ThreadPoolExecutor) 
Executors.newFixedThreadPool(10);
         MarkSweepGarbageCollector gc = init(blobGcMaxAgeInSecs, executor);

Modified: 
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentDataStoreBlobGCIT.java
URL: 
http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentDataStoreBlobGCIT.java?rev=1754076&r1=1754075&r2=1754076&view=diff
==============================================================================
--- 
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentDataStoreBlobGCIT.java
 (original)
+++ 
jackrabbit/oak/trunk/oak-segment/src/test/java/org/apache/jackrabbit/oak/plugins/segment/SegmentDataStoreBlobGCIT.java
 Tue Jul 26 07:38:47 2016
@@ -28,6 +28,7 @@ import static org.junit.Assume.assumeTru
 
 import java.io.ByteArrayInputStream;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.Date;
@@ -45,13 +46,18 @@ import java.util.concurrent.TimeUnit;
 import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import ch.qos.logback.classic.Level;
 import com.google.common.base.Stopwatch;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Sets;
 import com.google.common.io.Closeables;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.FileFilterUtils;
 import org.apache.jackrabbit.oak.api.Blob;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.commons.FileIOUtils;
+import org.apache.jackrabbit.oak.commons.junit.LogCustomizer;
 import org.apache.jackrabbit.oak.plugins.blob.BlobReferenceRetriever;
 import org.apache.jackrabbit.oak.plugins.blob.GarbageCollectorFileState;
 import org.apache.jackrabbit.oak.plugins.blob.MarkSweepGarbageCollector;
@@ -134,6 +140,10 @@ public class SegmentDataStoreBlobGCIT {
     }
 
     public DataStoreState setUp() throws Exception {
+        return setUp(10);
+    }
+
+    public DataStoreState setUp(int count) throws Exception {
         if (blobStore == null) {
             blobStore = DataStoreUtils.getBlobStore(folder.newFolder());
         }
@@ -158,7 +168,7 @@ public class SegmentDataStoreBlobGCIT {
 
         // 2. Now remove the nodes to generate garbage
         content = a.child("content");
-        for (int i = 0; i < 2000; i++) {
+        for (int i = 0; i < 500; i++) {
             NodeBuilder c = content.child("x" + i);
             for (int j = 0; j < 5; j++) {
                 c.removeProperty("p" + j);
@@ -168,7 +178,7 @@ public class SegmentDataStoreBlobGCIT {
 
         /* Create and delete nodes with blobs stored in DS*/
         int maxDeleted  = 5;
-        int numBlobs = 10;
+        int numBlobs = count;
         List<Integer> processed = Lists.newArrayList();
         Random rand = new Random();
         for (int i = 0; i < maxDeleted; i++) {
@@ -256,7 +266,27 @@ public class SegmentDataStoreBlobGCIT {
         Set<String> existingAfterGC = gcInternal(0);
         assertTrue(Sets.symmetricDifference(state.blobsPresent, 
existingAfterGC).isEmpty());
     }
-    
+
+    @Test
+    public void checkMark() throws Exception {
+        LogCustomizer customLogs = LogCustomizer
+            .forLogger(MarkSweepGarbageCollector.class.getName())
+            .enable(Level.TRACE)
+            .filter(Level.TRACE)
+            .create();
+
+        DataStoreState state = setUp(2000);
+        log.info("{} blobs available : {}", state.blobsPresent.size(), 
state.blobsPresent);
+        customLogs.starting();
+        ThreadPoolExecutor executor = (ThreadPoolExecutor) 
Executors.newFixedThreadPool(10);
+        String rootFolder = folder.newFolder().getAbsolutePath();
+        MarkSweepGarbageCollector gcObj = init(0, executor, rootFolder);
+        gcObj.collectGarbage(true);
+        customLogs.finished();
+
+        assertBlobReferenceRecords(state.blobsPresent, rootFolder);
+    }
+
     @Test
     public void noGc() throws Exception {
         DataStoreState state = setUp();
@@ -374,8 +404,34 @@ public class SegmentDataStoreBlobGCIT {
         log.info("{} blobs existing after gc : {}", existingAfterGC.size(), 
existingAfterGC);
         return existingAfterGC;
     }
-    
-    private MarkSweepGarbageCollector init(long blobGcMaxAgeInSecs, 
ThreadPoolExecutor executor) throws Exception {
+
+    private static void assertBlobReferenceRecords(Set<String> expected, 
String rootFolder) throws IOException {
+        // Read the marked files to check if paths logged or not
+        File root = new File(rootFolder);
+        List<File> rootFile = FileFilterUtils.filterList(
+            FileFilterUtils.prefixFileFilter("gcworkdir-"),
+            root.listFiles());
+        List<File> markedFiles = FileFilterUtils.filterList(
+            FileFilterUtils.prefixFileFilter("marked-"),
+            rootFile.get(0).listFiles());
+        InputStream is = null;
+        try {
+            is = new FileInputStream(markedFiles.get(0));
+            Set<String> records = FileIOUtils.readStringsAsSet(is, true);
+            assertEquals(expected, records);
+        } finally {
+            Closeables.close(is, false);
+            FileUtils.forceDelete(rootFile.get(0));
+        }
+    }
+
+    private MarkSweepGarbageCollector init(long blobGcMaxAgeInSecs, 
ThreadPoolExecutor executor)
+        throws Exception {
+        return init(blobGcMaxAgeInSecs, executor, 
folder.newFolder().getAbsolutePath());
+    }
+
+    private MarkSweepGarbageCollector init(long blobGcMaxAgeInSecs, 
ThreadPoolExecutor executor,
+        String root) throws Exception {
         String repoId = null;
         if (SharedDataStoreUtils.isShared(store.getBlobStore())) {
             repoId = ClusterRepositoryInfo.getOrCreateId(nodeStore);
@@ -383,10 +439,10 @@ public class SegmentDataStoreBlobGCIT {
                 new ByteArrayInputStream(new byte[0]), 
                 REPOSITORY.getNameFromId(repoId));
         }
-        MarkSweepGarbageCollector gc = new MarkSweepGarbageCollector(
-            new SegmentBlobReferenceRetriever(store.getTracker()),
-            (GarbageCollectableBlobStore) store.getBlobStore(), executor, 
folder.newFolder().getAbsolutePath(), 2048, blobGcMaxAgeInSecs,
-            repoId);
+        MarkSweepGarbageCollector gc =
+            new MarkSweepGarbageCollector(new 
SegmentBlobReferenceRetriever(store.getTracker()),
+                (GarbageCollectableBlobStore) store.getBlobStore(), executor,
+                root, 2048, blobGcMaxAgeInSecs, repoId);
         return gc;
     }    
 


Reply via email to