You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by md...@apache.org on 2015/08/05 15:25:33 UTC

svn commit: r1694208 - /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java

Author: mduerig
Date: Wed Aug  5 13:25:32 2015
New Revision: 1694208

URL: http://svn.apache.org/r1694208
Log:
OAK-3179: Deadlock between persisted compaction map and cleanup
Move CompactionMap.remove() call outside the synchronized block

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java?rev=1694208&r1=1694207&r2=1694208&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/segment/file/FileStore.java Wed Aug  5 13:25:32 2015
@@ -653,44 +653,49 @@ public class FileStore implements Segmen
      * A new generation of a tar file is created (and segments are only
      * discarded) if doing so releases more than 25% of the space in a tar file.
      */
-    public synchronized void cleanup() throws IOException {
+    public void cleanup() throws IOException {
         Stopwatch watch = Stopwatch.createStarted();
         long initialSize = size();
-        gcMonitor.info("TarMK revision cleanup started. Current repository size {}",
-                humanReadableByteCount(initialSize));
+        CompactionMap cm = tracker.getCompactionMap();
+        Set<UUID> cleanedIds = newHashSet();
 
-        newWriter();
-        tracker.clearCache();
+        synchronized (this) {
+            gcMonitor.info("TarMK revision cleanup started. Current repository size {}",
+                    humanReadableByteCount(initialSize));
 
-        // Suggest to the JVM that now would be a good time
-        // to clear stale weak references in the SegmentTracker
-        System.gc();
-
-        Set<UUID> ids = newHashSet();
-        for (SegmentId id : tracker.getReferencedSegmentIds()) {
-            ids.add(new UUID(
-                    id.getMostSignificantBits(),
-                    id.getLeastSignificantBits()));
-        }
-        writer.collectReferences(ids);
+            newWriter();
+            tracker.clearCache();
 
-        CompactionMap cm = tracker.getCompactionMap();
-        List<TarReader> list = newArrayListWithCapacity(readers.size());
-        Set<UUID> cleanedIds = newHashSet();
-        for (TarReader reader : readers) {
-            TarReader cleaned = reader.cleanup(ids, cm, cleanedIds);
-            if (cleaned == reader) {
-                list.add(reader);
-            } else {
-                if (cleaned != null) {
-                    list.add(cleaned);
+            // Suggest to the JVM that now would be a good time
+            // to clear stale weak references in the SegmentTracker
+            System.gc();
+
+            Set<UUID> ids = newHashSet();
+            for (SegmentId id : tracker.getReferencedSegmentIds()) {
+                ids.add(new UUID(
+                        id.getMostSignificantBits(),
+                        id.getLeastSignificantBits()));
+            }
+            writer.collectReferences(ids);
+
+            List<TarReader> list = newArrayListWithCapacity(readers.size());
+            for (TarReader reader : readers) {
+                TarReader cleaned = reader.cleanup(ids, cm, cleanedIds);
+                if (cleaned == reader) {
+                    list.add(reader);
+                } else {
+                    if (cleaned != null) {
+                        list.add(cleaned);
+                    }
+                    File file = reader.close();
+                    gcMonitor.info("TarMK revision cleanup reclaiming {}", file.getName());
+                    toBeRemoved.addLast(file);
                 }
-                File file = reader.close();
-                gcMonitor.info("TarMK revision cleanup reclaiming {}", file.getName());
-                toBeRemoved.addLast(file);
             }
+            readers = list;
         }
-        readers = list;
+
+        // Do this outside sync to avoid deadlock with SegmentId.getSegment(). See OAK-3179
         cm.remove(cleanedIds);
         long finalSize = size();
         gcMonitor.cleaned(initialSize - finalSize, finalSize);